2018年东北地区赛S - Problem I. Spell Boost HDU - 6508

2018年东北地区赛S - Problem I. Spell Boost HDU - 6508,第1张

概述  题目地址:https://vjudge.net/problem/HDU-6508 思路: 给一些卡,分为四种卡。 1.白卡(没效果) 2.魔法,作用卡(会对作用卡的费用减少,也会被魔法卡作用) 3.作用卡(会被魔法卡作用使其费用减少) 4.魔法卡(会对作用卡的费用减少) 有一个想法:如果我们得到最大的攻击力,其中会用到魔法卡和作用卡或者两者效果都有的卡的话,魔法卡其实是越早用越好 ,而作用卡越   题目地址:https://vjudge.net/problem/HDU-6508

思路:
给一些卡,分为四种卡。
1.白卡(没效果)
2.魔法,作用卡(会对作用卡的费用减少,也会被魔法卡作用)
3.作用卡(会被魔法卡作用使其费用减少)
4.魔法卡(会对作用卡的费用减少)

有一个想法:如果我们得到最大的攻击力,其中会用到魔法卡和作用卡或者两者效果都有的卡的话,魔法卡其实是越早用越好
,而作用卡越晚用晚用越好,因为作用卡会被魔法卡影响,使其费用减少,而且费用少的卡需要先使用,才能尝试更多的可能,
如果一张卡是10w,一张卡是1w,为了尝试更多可能,先让费用少的先尝试,让费用多的之后对dp[N][N]进行比较。
那么,dp[N][N],第一个维度为费用值,第二个维度为用了几张魔法卡,维护的是最大攻击力。
然后就是一个01背包问题,当然为了实现我们的想法,需要对结构体进行某些特定的排序。

 

 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,k) for(int i = (j); i >= (k); i--) 6  7 const int N = 510;  8 int dp[N][N];  9  10 struct node{  11     int w,x;  12     int is_m,is_s;  13  14     bool frIEnd operator < (node a,node b){  15         if (a.is_m != b.is_m) return a.is_m > b.is_m;//魔法卡先返回 16         else if (a.is_s != b.is_s) return a.is_s < b.is_s;//作用卡越晚用越好 17  18         return a.w < b.w;//先用费用小的,使其dp可以得到全部可能 19  }  20 };  21  22 node arr[N];  23  24 voID init(int x){  25 // rep(i,x)rep(j,x) dp[i][j] = 0; 26     memset(dp,0,sizeof(dp));  27 }  28  29 int main(){  30  31     ios::sync_with_stdio(false);  32     cin.tIE(0);  33  34     int n,W;  35     while (cin >> n >> W){  36  37         int m_num = 0;  38  39         rep(i,1,n){  40             cin >> arr[i].w >> arr[i].x >> arr[i].is_m >> arr[i].is_s;  41             if (arr[i].is_m) ++m_num;//统计魔法卡数量 42  }  43  44  init(n);  45  46         sort(arr + 1,arr + 1 + n);  47  48         bool is_s = false;//判断是不是作用卡  49         //从大到小遍历,可以不影响之前的状态 50         rep(i,n){  51             if (arr[i].is_m){  52  53                 per(k,i,1){//魔法卡从多到少 54                     per(j,W,0){//费用从多到少 55  56                         int tmp_w = 0;  57                         if (arr[i].is_s){//有被作用效果 58                             is_s = true;  59                             tmp_w = max(0,arr[i].w - (k - 1));//触发魔法卡效果 60  }  61                         //对于k张魔法卡,之前只有k-1张魔法卡,假如一张魔法卡去更新dp,所以被作用时  62                         //应该是魔法卡数量-1的费用减少 63                         if (is_s && tmp_w <= j){//是作用卡,费用足够 64                             dp[j][k] = max(dp[j][k],dp[j - tmp_w][k - 1] + arr[i].x);  65  }  66                         else if (!is_s && arr[i].w <= j){//不是作用卡,费用足够 67                             dp[j][k] = max(dp[j][k],dp[j - arr[i].w][k - 1] + arr[i].x);  68  }  69  }  70  }  71  }  72             else {  73                 //进入该部分时,全部的魔法卡使用情况已经存入dp,之后的都不是魔法卡 74                 per(k,m_num,0){//m_num是魔法卡总数量,可能有不用魔法卡才能的到最大攻击的情况 75                     per(j,0){  76                          77                         int tmp_w = 0;  78                         if (arr[i].is_s){  79                             is_s = true;  80                             tmp_w = max(0,arr[i].w - k);  81  }  82                         //对于k张魔法卡,被作用卡卡费用减少k 83                         if (is_s && tmp_w <= j){  84                             dp[j][k] = max(dp[j][k],dp[j - tmp_w][k] + arr[i].x);  85  }  86                         else if (!is_s && arr[i].w <= j){  87                             dp[j][k] = max(dp[j][k],dp[j - arr[i].w][k] + arr[i].x);  88  }  89  }  90  }  91  }  92  93             is_s = false;  94  }  95  96         int ans = 0;  97  98         rep(i,m_num) ans = max(ans,dp[W][i]);//遍历费用是W的dp最大值,及为最大攻击力 99 100         cout << ans << endl; 101  } 102 103 104     return 0; 105 }
总结

以上是内存溢出为你收集整理的2018年东北地区赛S - Problem I. Spell Boost HDU - 6508全部内容,希望文章能够帮你解决2018年东北地区赛S - Problem I. Spell Boost HDU - 6508所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/1228625.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存