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;

}

你可能感兴趣的:(ZOJ)