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;
}
浙公网安备 33010602011771号