HDOJ 6508 Problem I. Spell Boost (01背包/DP)

链接http://acm.hdu.edu.cn/showproblem.php?pid=6508


题目:

Problem Description
Shadowverse is a funny card game. One day you are playing a round of this game.
You have n cards, each with two attributes wi and xi. If you use card i, you will cost wi points of power and cause xi damage to the enemy.
Among them, there are two special types of cards: some cards are magic cards and some have “spell boost effect”. Everytime you have used a magic card, for each unused “spell boost effect” card i: if the the current cost of i (i.e. wi) is positive, then wi will be reduced by 1. Note that some cards may be both
magic cards and have spell boost effect.
Now you have W points of power, you need to calculate maximum total damage you can cause.
 
Input
Input is given from Standard Input in the following format:
n W
w1 x1 is_magic1 is_spell_boost1
w2 x2 is_magic2 is_spell_boost2
...
...
...
wn xn is_magicn is_spell_boostn

Constraints
1 ≤ n ≤ 500
0 ≤ W, wi, xi ≤ 500, and all of them are integers.
is_magici means: If this card is magic card, the value is 1, otherwise the value is 0.
is_spell_boosti means: If this card has spell boost effect, the value is 1, otherwise 0
 
Output
One integer representing the maximum total damage.
 
Sample Input
3 3
3 3 1 1
2 3 1 1
1 3 1 1
4 3
3 3 1 1
3 4 1 0
1 3 0 1
1 0 1 0
 
Sample Output
9
7
 
 

 

题意:

给出四种卡片 既是魔法卡也是增幅卡 是魔法卡不是增幅卡 是增幅卡不是魔法卡 不是增幅卡也不是魔法卡

每一张卡片都包含两个值 打出牌的代价 和打出牌的价值

其中魔法卡的作用是使所有未使用的增幅卡代价减1 如果代价已经为0就不减了

思路:

从增幅卡和魔法卡的作用中可以看出来 打出这四种牌是有先后顺序的 增幅卡要尽可能后打出 魔法卡要尽可能先打出

我采用的顺序是 是魔法卡不是增幅卡>是增幅卡不是魔法卡>既是魔法卡也是增幅卡>不是增幅卡也不是魔法卡

然后采用三维dp来转移 dp[i][j][k]表示的是当前已经打出的伤害和 i表示当前已经打到的第i张牌 j表示当前已经打出的增幅卡的数量 k表示当前已经用掉的代价和

直接用三维去存储的话存不下 采用了滚动数组去滚掉第一维i(当前的位置只依赖上一位 可以采用滚动数组只记录两个值 i%2和(i-1)%2)


代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn=550;
int n,W;
int dp[2][maxn][maxn];

struct node{
    int w,x,vis1,vis2;
}kk[maxn];

int cmp(node a,node b){
    if(a.vis1!=b.vis1) return a.vis1>b.vis1;
    if(a.vis2!=b.vis2) return a.vis2<b.vis2;
    return a.w<b.w;
}

int main(){
 //   freopen("1.in","r",stdin);
    while(~scanf("%d%d",&n,&W)){
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d",&kk[i].w,&kk[i].x,&kk[i].vis1,&kk[i].vis2);
        }
        sort(kk+1,kk+1+n,cmp);
        memset(dp[0],-1,sizeof(dp[0]));
        dp[0][0][0]=0;
      //  cout<<n<<endl;
        for(int i=1;i<=n;i++){
            memset(dp[i%2],-1,sizeof(dp[i%2]));
            for(int j=0;j<=i;j++){
                for(int k=0;k<=W;k++){
                //    if(dp[(i-1)%2][j][k]==-1) continue;
                    dp[i%2][j][k]=dp[(i-1)%2][j][k];
                    if(kk[i].vis1==1 && kk[i].vis2==1 && j-1>=0 && k-max(kk[i].w-(j-1),0)>=0 && dp[(i-1)%2][j-1][k-max(kk[i].w-(j-1),0)]!=-1) 
                        dp[i%2][j][k]=max(dp[i%2][j][k],dp[(i-1)%2][j-1][k-max(kk[i].w-(j-1),0)]+kk[i].x); //既是魔法卡也是增幅卡
                    if(kk[i].vis1==0 && kk[i].vis2==1 && k-max(kk[i].w-j,0)>=0 && dp[(i-1)%2][j][k-max(kk[i].w-j,0)]!=-1) 
                        dp[i%2][j][k]=max(dp[i%2][j][k],dp[(i-1)%2][j][k-max(kk[i].w-j,0)]+kk[i].x); //只是增幅卡
                    if(kk[i].vis1==1 && kk[i].vis2==0 && j-1>=0 && k-kk[i].w>=0 && dp[(i-1)%2][j-1][k-kk[i].w]!=-1) 
                        dp[i%2][j][k]=max(dp[i%2][j][k],dp[(i-1)%2][j-1][k-kk[i].w]+kk[i].x); //只是魔法卡
                    if(kk[i].vis1==0 && kk[i].vis2==0 && k-kk[i].w>=0 && dp[(i-1)%2][j][k-kk[i].w]!=-1) 
                        dp[i%2][j][k]=max(dp[i%2][j][k],dp[(i-1)%2][j][k-kk[i].w]+kk[i].x); //什么都不是
                }
            }
        }
        int ans=0;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=W;j++){
                ans=max(ans,dp[n%2][i][j]);
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/whdsunny/p/10748634.html