Problem I. Spell Boost(dp 状态之间的影响)

原题: http://acm.hdu.edu.cn/showproblem.php?pid=6508

题意:

有n个卡片,是否为魔法卡,是否可以减费。卡片会消耗w能量,造成x伤寒。每使用一张魔法卡,接下来的可减费的卡消耗-1。初始值为W,问最大伤害。

解析:

用dp[i][j]表示还剩i能量,用了j张魔法的最大伤害。

考虑四种卡片:

  • 物理卡不可减费:直接做背包,因为即不会影响别的,又不会被影响。
  • 魔法卡不可减费:第二个做,会对接下来两个牌造成影响,但是不受影响。
  • 魔法卡可减费:被第二种卡影响,还会影响第四种。
  • 物理卡可减费:被第二、三种影响。

其中注意做第三种卡的时候需要按照法力值升序排序。因为有些魔力消耗大的卡可能被小的那些减费,但是直接上的话魔力值不够就变成负数而不考虑这种情况。

做背包的时候要注意状态的枚举是从大到小还是从小到大。如果转移到较大状态则从大到小,反之亦然。(因为是01包)

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod =1e9+7;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repp(i,b,a) for(int i=b;i>=a;i--)

inline char nc(){
  static char buf[1000000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,1000000,stdin); if (p1==p2) return EOF; }
  return *p1++;
}

inline void read(int &x){
  char c=nc(),b=1;
  if(c==EOF){
      x=-1;
      return ;
  }
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}


int n,W;
int a[4][2][509];
int top[4];
int dp[509][509];
struct node{
    int x,w;
    bool operator<(const node &R)const{
        return w<R.w;
    }
}e[509];

int main(){
    while(read(n),n!=-1){
        memset(dp,0xc0,sizeof dp);
        read(W);
        dp[W][0]=0;
        rep(i,0,3)top[i]=0;
        rep(i,1,n){
            int w,x,mg,can;
            read(w),read(x),read(mg),read(can);
            if(!mg&&!can){
                a[0][0][++top[0]]=w;
                a[0][1][top[0]]=x;
            }
            else if(mg&&!can){
                a[1][0][++top[1]]=w;
                a[1][1][top[1]]=x;
            }
            else if(mg&&can){
                a[2][0][++top[2]]=w;
                a[2][1][top[2]]=x;
            }
            else{
                a[3][0][++top[3]]=w;
                a[3][1][top[3]]=x;
            }
        }
        rep(i,1,top[2]){
            e[i].w=a[2][0][i];
            e[i].x=a[2][1][i];
        }
        sort(e+1,e+1+top[2]);
        rep(i,1,top[2]){
            a[2][0][i]=e[i].w;
            a[2][1][i]=e[i].x;
        }
        rep(i,1,top[0]){
            int w=a[0][0][i],x=a[0][1][i];
            rep(j,w,W){
                if(dp[j][0]>-1e8){
                    dp[j-w][0]=max(dp[j-w][0],dp[j][0]+x);
                }
            }
        }
        rep(i,1,top[1]){
            int w=a[1][0][i],x=a[1][1][i];
            rep(j,w,W){
                repp(k,i-1,0){
                    if(dp[j][k]>-1e8){
                        dp[j-w][k+1]=max(dp[j-w][k+1],dp[j][k]+x);
                    }
                }
            }
        }
        rep(i,1,top[2]){
            int x=a[2][1][i];
            repp(k,i-1+top[1],0){
                int w=max(0,a[2][0][i]-k);
                rep(j,w,W){
                    if(dp[j][k]>-1e8){
                        dp[j-w][k+1]=max(dp[j-w][k+1],dp[j][k]+x);
                    }
                }
            }
        }
        rep(i,1,top[3]){
            int x=a[3][1][i];
            repp(k,top[2]+top[1],0){
                int w=max(0,a[3][0][i]-k);
                rep(j,w,W){
                    if(dp[j][k]>-1e8){
                        dp[j-w][k]=max(dp[j-w][k],dp[j][k]+x);
                    }
                }
            }
        }
        int ans=-1;
        rep(i,0,W){
            rep(j,0,top[1]+top[2]){
                ans=max(ans,dp[i][j]);
            }
        }
        printf("%d\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/89436324