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]表示打的前一个状态.代码如下:

#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;
}

posted @ 2011-07-18 17:07  书山有路,学海无涯  阅读(345)  评论(0编辑  收藏  举报