zoukankan      html  css  js  c++  java
  • Codeforces Round #565 (Div. 3) F.Destroy it!

     

    题目地址: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张三费卡


      1 #include<iostream>
      2 #include<algorithm>
      3 using namespace std;
      4 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
      5 #define per(i,j,k) for(int i = (j); i >= (k); i--)
      6 #define mod(x) ((x)%(MOD))
      7 
      8 typedef long long LL;
      9 const int MOD = 10;
     10 const int N = 2e5 + 10;
     11 LL dp[N + 2][10];
     12 
     13 void init(){
     14     rep(i, 0, N) rep(j, 0, 9) dp[i][j] = -1;
     15 }
     16 
     17 int main(){
     18 
     19     ios::sync_with_stdio(false);
     20     cin.tie(0);
     21 
     22     init();
     23 
     24     int n;
     25     cin >> n;
     26 
     27     dp[0][0] = 0;//初始化
     28 
     29     rep(o, 1, n){
     30         int num;
     31         cin >> num;
     32 
     33         int L1 = 0;
     34         int L2 = 0;
     35         int L3 = 0;
     36         int c1[5] = { 0 };//费用1,记录v最大的三张
     37         int c2 = 0;//费用2
     38         int c3 = 0;//费用3
     39 
     40         int c, v;
     41         rep(i, 1, num){
     42             cin >> c >> v;
     43 
     44             if (c == 1){
     45                 if (L1 == 3){
     46                     int x = 1;
     47                     if (c1[x] > c1[2]) x = 2;
     48                     if (c1[x] > c1[3]) x = 3;
     49                     if (v > c1[x]) c1[x] = v;
     50                 }
     51                 else c1[++L1] = v;
     52             }
     53             else if (c == 2){
     54                 L2 = 1;
     55                 if (v > c2) c2 = v;
     56             }
     57             else if (c == 3){
     58                 L3 = 1;
     59                 if (v > c3) c3 = v;
     60             }
     61         }
     62 
     63         sort(c1 + 1, c1 + 1 + 3);
     64 
     65         int max_v = max(c1[3], max(c2, c3));//一张v最大的
     66         int _2_1 = c1[3];//两张卡费用最大的
     67         int _2_2 = c1[2];
     68         if (c2 > _2_2) _2_2 = c2;
     69         if (_2_2 > _2_1) swap(_2_2, _2_1);//两张卡,由1费中间v最大的2张,和一张2费的中间选出v最大的两张
     70         LL _3 = c1[1] + c1[2] + c1[3];//用三张1费
     71 
     72         rep(i, 0, 9) dp[o][i] = dp[o - 1][i];//先把上个回合的状态保存到当前回合,方便下边的比较
     73         //因为这三种状态都是附加在上个状态下得出的,所以他们之间都是独立的。
     74         //mod(i + x),(i + x >= 10)* value 用于判断是否满足大于等于用的次数是十张的倍数
     75         rep(i, 0, 9){
     76             if (dp[o - 1][i] != -1){//上个状态是存在的
     77                 if (L1 + L2 + L3 >= 1){//用的卡牌最少一张的时候,用一张情况
     78 
     79                     dp[o][mod(i + 1)] = max(dp[o][mod(i + 1)], 
     80                                            dp[o - 1][i] + max_v + (i + 1 >= 10)*max_v);
     81 
     82                 }
     83                 if (L2 + L1 >= 2){//1费2费用的卡牌至少有两张,用两张情况
     84 
     85                     dp[o][mod(i + 2)] = max(dp[o][mod(i + 2)], 
     86                                           dp[o - 1][i] + _2_1 + _2_2 + (i + 2 >= 10)*_2_1);
     87 
     88                 }
     89                 if (L1 >= 3){//1费卡牌数最少三张,用三张情况
     90 
     91                     dp[o][mod(i + 3)] = max(dp[o][mod(i + 3)],
     92                                           dp[o - 1][i] + _3 + (i + 3 >= 10)*c1[3]);    
     93 
     94                 }
     95             }
     96         }
     97     }
     98 
     99     LL ans = -1;
    100 
    101     //rep(i, 0, n){
    102     //    rep(o, 0, 9) cout << dp[i][o] << " ";
    103     //    cout << endl;
    104     //}
    105     //cout << endl;
    106 
    107     rep(o, 0, 9) ans = max(dp[n][o], ans);
    108 
    109     cout << ans << endl;
    110 
    111     return 0;
    112 }
  • 相关阅读:
    【noi 2.5_1789】算24(dfs)
    【bzoj 4455】小星星(树型DP+容斥原理+dfs建树和计算的2种方式)
    【bzoj 1190】梦幻岛宝珠(DP)
    【bzoj 3333】排队计划(线段树)
    【noi 2.5_7834】分成互质组(dfs)
    【noi 2.5_1792】迷宫(bfs 或 dfs)
    【noi 2.2_7891】一元三次方程求解(二分枚举+输出程序运行时间)
    JFrame包含的容器(JRootPane)
    JFrame背景色设置
    java自动装箱的一个例子
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/11163488.html
Copyright © 2011-2022 走看看