CF 385Div2 E题

两个操作,取一张红卡和一张黑卡,购买一个东西。问最少多少次操作能够买完所有东西。费用为max(r[i]-A,0)和max(b[i]-B,0)。

简单思路方向:dp,f[mask][i][j]表示,可是好像有点棘手。

技巧:反向模拟过程,假设现在已经买完东西了,枚举上一次买的是什么东西,以同样的方式就能写出相应的dp了,用map实现,这种方法不确定状态数多少,只能卡过去。

第二次优化:运用求补集的思想,我们可以把问题进一步简化,用f[mask][i]表示已经省下i张红卡所省下的做多黑卡数,因为根据费用公式,要想到影响费用的因素只有当前拥有的卡数量,并且影响的大小是A和B,然而A和B的数量级比较小,这样表示的优点在于避免r[i]和b[i]特别大而状态数很多,所以我们可以用比较小的A和B来记录状态,是一个重要的思维,时间复杂度为2^n*n*n。

时间: 2024-08-05 17:06:15

CF 385Div2 E题的相关文章

我要cf破1000题!!!

我现在cf是292题,还差1000-292=708题. 水平的提高确实和题数不完全相关,但是问题是现在训练强度确实太低了. 我打算在两个月之内达到1000题,也就是说1天至少10题,两个月60天,720/60=12题/天,平均每天做12题就完成任务了. 为了提高效率,我应该不会在一道题卡两个小时以上,会直接看题解,保证平均40分钟补一个题.

CF 19C 思维题STL应用

http://codeforces.com/problemset/problem/19/C Once Bob saw a string. It contained so many different letters, that the letters were marked by numbers, but at the same time each letter could be met in the string at most 10 times. Bob didn't like that s

CF 某套题 O :Grid (简单BFS)

题意: 从左上角跳到右下角最少需要多少步,跳的规则为:可以向四个方向的任意一个方向跳当前格子中的步数,若跳不到右下角输出IMPOSSIBLE. 题解: BFS搜索,注意判断边界,标记. 代码: #include <iostream> #include <cstdio> #include <algorithm> #include <stdio.h> #include <cmath> #include <cstring> #include

CF每日一题系列 —— 415A

http://codeforces.com/problemset/page/7?order=BY_SOLVED_DESC 从5000以内选的,emmm还是比较水的哈 时间还是有的,所以万事万物贵在坚持,希望能坚持下去! Describe: 1 - n个灯线性排列(初始为开),小明可以选择开关 op,这回把op - n 的灯全部关闭,如果(是关着的状态没有影响) 给你小明选择op的操作顺序,输出顺序输出每个灯是由哪个op操作关了的 Solution: 跑暴力就好了,我用了一个比较水的优化,记录当前

[ 9.11 ]CF每日一题系列—— 441C暴力模拟

Description: n * m 的地图,建设k个管道管道只能横竖走,且长度大于等于2,问你任意一种建设方法 Solution: 图里没有障碍,所以先把前k - 1个管道每个分2个长度,最后一个管道一连到底 Code: PS:今天时间没来的急,其实函数可以封装一下的,虽然都是暴力,但也得暴力的优美不是?? #include <iostream> #include <cstdio> using namespace std; int main() { int n,m,k; whil

[ 9.12 ]CF每日一题系列—— 960B暴力数组

Description: 给你两个数组,顺序一定,问你第一个数组连续的几个值等于下一个数组连续的几个值,然后寻找这个值得最大值,也就是满足就换 Solution: 用两个变量索引,判断即可 #include <iostream> #include <cstdio> using namespace std; const int maxn = 1e6 + 1e3; int a[maxn],b[maxn]; int main() { int n,m; while(~scanf("

[ 9.22 ]CF每日一题系列—— 484A Bits

Description: 给你一个l,r的区间让你找一个最小的x并且其二进制数要包含最多的1位,输出它的十进制 Solution: 我本来就是贪心,但是贪大了,想1一直往上添加1,但是忘记了0在中间的情况,考虑好了之后,发现这样贪是错误的,因为越往后位数越大,所以你最后的结果只能是1,11,111,1111,11111,而不可能是10,100,1001,10010,所以应该从后往前贪,这也是我们十进制转二进制的人工算法吧算是,十进制转二进制,手算的时候,就是一步一步确定最高位的1在哪里, cod

[ 9.26 ]CF每日一题系列—— 771B递推问题

Description: 给定你命名的规律,1-10个字符,开头必须大写,最多有50个名字,然后告诉你有n个人,判断区间长度为k,那么你将得到n - k + 1个答案(YES or NO) 表示1 - k,2 -k+1,n - K + 1-- n这些人里面是否没有重名,YES没有,NO有,让你推出一种名字的组合方式 Solution: 首先先跑出一个名字数组,这个题目要往后看,所以应该是从后往前推n - k + 2 到 n的名字没有要求,所以我们命名各不相同,从n - k + 1开始,如果是YE

[ 10.03 ]CF每日一题系列—— 534B贪心

Descripe: 贪心,贪在哪里呢-- 给你初始速度,结尾速度,行驶秒数,每秒速度可变化的范围,问你行驶秒数内最远可以行驶多少距离 Solution: 贪心,我是否加速,就是看剩下的时间能不能减到原始给定的结尾速度 #include <iostream> using namespace std; int main() { int v1,v2; int t,d; while(cin>>v1>>v2) { cin>>t>>d; int ret =