HDU4539-郑厂长系列故事——排兵布阵

郑厂长不是正厂长
  也不是副厂长
  他根本就不是厂长
  事实上
  他是带兵打仗的团长

一天,郑厂长带着他的军队来到了一个nm的平原准备布阵。
  根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
  现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
Input
输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n
m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
Output
请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。
Sample Input
6 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
Sample Output
2

分析:

题意:
中文题目,基本都可以懂!

解析:
哈顿曼距离为2的位置不能安排士兵,即如果一个位置(x1,y1)的地方安排了士兵,那么|x1-x2|+|y1-y2|==2地方不能安排士兵。

开始我的DP数组开的二维,但是一直WA,经过仔细的检查,我发现在三行的情况下,虽然这三行实现了互斥,但是中间那一行第一行之前的那一行是否实现互斥我们是无从可知的,因为我们总是要求前面已经排列好的行与新添加的行的士兵总数最大。

代码:

#include
#include
#include
#include
#define N 105

using namespace std;

int n,m;
int map[N][N];
int dp[N][N<<1][N<<1];
int OK[1<<10];
int Num[1<<10];

int Getnum(int x)
{
	int num=0;
	while(x)
	{
		if(x&1)
			num++;
		x>>=1;
	}
	return num;
}

bool cmp(int i,int x)
{
	for(int j=1;j<=m;j++)
	{
		if(!map[i][j])
		{
			if((x>>(m-j))&1)
				return false;
		}
	}
	return true;
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				scanf("%d",&map[i][j]); 
			}
		}
		int num=0,sum=0;
		for(int i=0;i<(1<<m);i++)
		{
			if(!(i&(i<<2)))
			{
				OK[++num]=i;
				Num[num]=Getnum(i);
			}
		}
		memset(dp,0,sizeof(dp)); 
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=num;j++)
			{
				if(cmp(i,OK[j]))
				{
					for(int k=1;k<=num;k++)
					{
						if((OK[j]&(OK[k]<<1))||(OK[j]&(OK[k]>>1)))
							continue;
						if(cmp(i-1,OK[k]))
						{
							if(i==1)
							{
								dp[i][j][k]=Num[j];
								sum=max(dp[i][j][k],sum);
								continue;
							}
							int tmp=0;
							for(int t=1;t<=num;t++)
							{
								if((OK[t]&(OK[k]<<1))||(OK[t]&(OK[k]>>1)))
									continue;
								if(OK[j]&OK[t])
									continue;
								if(cmp(i-2,OK[t]))
								{
									tmp=max(dp[i-1][k][t],tmp);
								}
							}
							dp[i][j][k]=tmp+Num[j];
							sum=max(dp[i][j][k],sum);
						}
					}
				}
			}
		}
		printf("%d\n",sum);
	}
	return 0;
 }

你可能感兴趣的:(动态-状态压缩)