zoj 2297 状态压缩DP
其实也就是求打完boss之前的所有character 剩下PH的最大值,在和boss比较,若大于boss则赢,否则则输。打boss之前的所有角色的顺序不同,剩余的PH则不同。所以将前面的n-1个角色全排列就有2^(n-1)种可能。这几乎是不可能求出来的。每个角色在打的过程之中有两种可能打和不打,打用1表示,不打用0表示,那么20个数就可以用20位来表示,所以0~2^(n-1)每个数都表示一个状态,每个数之间都可以互相转化。假设dp[i][j]表示打j状态为i的剩余PH,那么状态转移方程就可以写为:dp[i][j]=max{dp[i][j],dp[i-j][k]+a[j][1]-a[j][0]};dp[i-j][k]表示打i 的前一个状态.代码如下:
#include<iostream> #include<cstring> using namespace std; int a[1100000]; int main() { int people[20][2],i,j,n,m,k,s,boss; while(cin>>n) { for(i=0;i<n-1;i++) cin>>people[i][0]>>people[i][1]; cin>>boss; m=(1<<(n-1))-1; memset(a,0,sizeof(a)); a[0]=100; for(i=0;i<=m;i++) { for(j=0;j<n-1;j++) { k=1<<j; if(!(k&i) && a[i]>=people[j][0])//由状态i可以转化为i&k状态 { s=a[i]+people[j][1]-people[j][0]; if(s>a[i+k]) a[i+k]=s;//原来可能已经有值,则选择较大的 if(a[i+k]>100) a[i+k]=100; } } } if(a[m]>=boss) cout<<"clear!!!"<<endl; else cout<<"try again"<<endl; } return 0; }