题目地址:http://codeforces.com/contest/1176/problem/F

思路:其实就是一个01背包问题,只是添加了回合和每回合的01限制,和每当已用牌数到了10的倍数,那张卡会触发double攻击。

因为卡使用的多少会触发double效果,所以我们要记录攻击的同时记录卡的使用次数,可以由01背包dp[N][N]改变,

第一个维度是当前是第几个回合,第二个维度是记录卡在用了n张的情况下造成的攻击力,但是dp[N][N](N <= 2e5),

占用内存太大显然不行。于是想到用dp[N][10]。

(因为卡的数量可能很多,我们其实只要记录最多三张1费,一张2费,一张3费)
每个回合用卡情况最多3种:
1.用3张一费卡。
2.用2张一费卡,或者1张一费卡,1张二费卡
3.用1张一费卡,或者1张二费卡,或者1张三费卡


 #include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,j,k) for(int i = (j); i <= (k); i++)
#define per(i,j,k) for(int i = (j); i >= (k); i--)
#define mod(x) ((x)%(MOD)) typedef long long LL;
const int MOD = ;
const int N = 2e5 + ;
LL dp[N + ][]; void init(){
rep(i, , N) rep(j, , ) dp[i][j] = -;
} int main(){ ios::sync_with_stdio(false);
cin.tie(); init(); int n;
cin >> n; dp[][] = ;//初始化 rep(o, , n){
int num;
cin >> num; int L1 = ;
int L2 = ;
int L3 = ;
int c1[] = { };//费用1,记录v最大的三张
int c2 = ;//费用2
int c3 = ;//费用3 int c, v;
rep(i, , num){
cin >> c >> v; if (c == ){
if (L1 == ){
int x = ;
if (c1[x] > c1[]) x = ;
if (c1[x] > c1[]) x = ;
if (v > c1[x]) c1[x] = v;
}
else c1[++L1] = v;
}
else if (c == ){
L2 = ;
if (v > c2) c2 = v;
}
else if (c == ){
L3 = ;
if (v > c3) c3 = v;
}
} sort(c1 + , c1 + + ); int max_v = max(c1[], max(c2, c3));//一张v最大的
int _2_1 = c1[];//两张卡费用最大的
int _2_2 = c1[];
if (c2 > _2_2) _2_2 = c2;
if (_2_2 > _2_1) swap(_2_2, _2_1);//两张卡,由1费中间v最大的2张,和一张2费的中间选出v最大的两张
LL _3 = c1[] + c1[] + c1[];//用三张1费 rep(i, , ) dp[o][i] = dp[o - ][i];//先把上个回合的状态保存到当前回合,方便下边的比较
//因为这三种状态都是附加在上个状态下得出的,所以他们之间都是独立的。
//mod(i + x),(i + x >= 10)* value 用于判断是否满足大于等于用的次数是十张的倍数
rep(i, , ){
if (dp[o - ][i] != -){//上个状态是存在的
if (L1 + L2 + L3 >= ){//用的卡牌最少一张的时候,用一张情况 dp[o][mod(i + )] = max(dp[o][mod(i + )],
dp[o - ][i] + max_v + (i + >= )*max_v); }
if (L2 + L1 >= ){//1费2费用的卡牌至少有两张,用两张情况 dp[o][mod(i + )] = max(dp[o][mod(i + )],
dp[o - ][i] + _2_1 + _2_2 + (i + >= )*_2_1); }
if (L1 >= ){//1费卡牌数最少三张,用三张情况 dp[o][mod(i + )] = max(dp[o][mod(i + )],
dp[o - ][i] + _3 + (i + >= )*c1[]); }
}
}
} LL ans = -; //rep(i, 0, n){
// rep(o, 0, 9) cout << dp[i][o] << " ";
// cout << endl;
//}
//cout << endl; rep(o, , ) ans = max(dp[n][o], ans); cout << ans << endl; return ;
}

Codeforces Round #565 (Div. 3) F.Destroy it!的更多相关文章

  1. Codeforces Round #485 (Div. 2) F. AND Graph

    Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...

  2. Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

    Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/co ...

  3. Codeforces Round #501 (Div. 3) F. Bracket Substring

    题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...

  4. Codeforces Round #499 (Div. 1) F. Tree

    Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...

  5. Codeforces Round #376 (Div. 2)F. Video Cards(前缀和)

    题目链接:http://codeforces.com/contest/731/problem/F 题意:有n个数,从里面选出来一个作为第一个,然后剩下的数要满足是这个数的倍数,如果不是,只能减小为他的 ...

  6. Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)

    题目链接:http://codeforces.com/contest/474/problem/F 题意简而言之就是问你区间l到r之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数 ...

  7. Codeforces Round #325 (Div. 2) F. Lizard Era: Beginning meet in the mid

    F. Lizard Era: Beginning Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...

  8. Codeforces Round #271 (Div. 2) F题 Ant colony(线段树)

    题目地址:http://codeforces.com/contest/474/problem/F 由题意可知,最后能够留下来的一定是区间最小gcd. 那就转化成了该区间内与区间最小gcd数相等的个数. ...

  9. Codeforces Round #479 (Div. 3) F. Consecutive Subsequence (简单dp)

    题目:https://codeforces.com/problemset/problem/977/F 题意:一个序列,求最长单调递增子序列,但是有一个要求是中间差值都是1 思路:dp,O(n)复杂度, ...

随机推荐

  1. JS超链接动态显示图片

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  2. WPF后台生成datatemplate(TreeViewItem例子)

    public void loadCheckListDataTemplate(TreeViewItem tvi) { DataTemplate cdt = new DataTemplate(); Fra ...

  3. Linux下的帮助命令

    内建命令,外部命令,命令别名:使用:type 命令名,查看 内建命令是shell一部分,一开始就加载进内存,程序一般简单:外部命令反之 2.  帮助命令的使用 内建命令:help 命令名:外部命令:命 ...

  4. 程序员该如何过好他的整个职业生涯?(最重要的是你得一直往前走。拐点不是你的工资。想起很久前有个人说我“逻辑性”比较强)good

    作者|池建强 编辑|小智   戳阅读原文,获得短信提醒,不错过下次InfoQ大咖说直播! 1 写在前面 加入极客邦的第一天就被拉到了「大咖说」的现场,这也是我始料未及的事情.从锤子科技正式离职之后,我 ...

  5. Linux之mysql安装

    查看文件内容的命令有很多:cat, tac, more, less, head, tail, nl. cat由第一行开始显示档案内容:tac从最后一行开始显示,可以看出tac是cat的倒着写:more ...

  6. 什么是Android NDK

    1.NDK是一系列工具的集合. NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk.这些工具对开发者的帮助是巨大的. NDK集成了交叉编译 ...

  7. <房间内功能>打赏小动画

    截图如下 :        功能:   每次点击礼物,都要通过动画显示一个小图标,最多显示两行图标栏,送多次会显示然后再次显示,显示 XX 送给 XX 一个小礼物的动画样式.动画样式效果为,整体动画模 ...

  8. C语言实现常用数据结构——栈

    #include<stdio.h> #include<stdlib.h> //用链表实现栈 typedef struct Node { int data; struct Nod ...

  9. c++汉诺塔相关知识总结1

    困扰已久,难以攻克的汉诺塔总结来啦 Part One 汉诺塔到底是什么呢? 汉诺塔(Tower of Hanoi)源于印度传说中,大梵天创造世界时造了三根金钢石柱子,其中一根柱子自底向上叠着64片黄金 ...

  10. vue项目接入api接口

    我们在做项目时,一切基础在于数据上面,所以接入api接口是关键. 访问接口是我们会遇到跨域,而,vue-cli给我们提供了反向代理,所以我们只需要配置一下就可以了. 在config文件中找到index ...