码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 4539 郑厂长系列故事——排兵布阵->状态压缩DP

时间:2015-06-08 01:05:56      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:c   c++   acm   算法   编程   

分析:dp[i][j][k]表示第i行状态为j,i-1行状态为k时的客房士兵的最大值。

曼哈顿距离是指:|x1-x2|+|y1-y2|。

当前行不仅与前一行有关,还和前两行有关,所以开数组的时候还要记录前两行的状态,所以开设三维数组。

每行可压缩为二进制集合,状态dp[i][j][k]为第i行为集合j,第i-1行为集合k,则状态方程dp[i][j][k] = max{dp[i-1][k][r]+cnt[j]  | 状态i,j,k要能够共存}(cnt[j]为j在二进制下的1的个数,即士兵数)。第一维可以压缩为2,即两种状态交替进行(这里没有压缩)。
对于每一行可能出现的组合,可预处理出每一种有效状态。

#include<iostream>
using namespace std;

int row[110];
int dp[110][220][220]; //dp[i][j][k]表示第i行状态为j,i-1行状态为k时的士兵最大值
int s[1<<11];        //合法状态
int cnt[1<<11];      //合法状态中1的个数,即可安排的士兵数

int get_cnt(int x)
{
	int c=0;

	while(x>0)
	{
		c++;
		x=x&(x-1);
	}
	return c;
}

int sovle(int n,int m)
{
	int state;     //一行一开始可安排士兵的合法状态总数(处理左右曼哈顿距离等于2的情况)
	int i,j,k,l,ans;

	state=0;
	for(i=0;i<(1<<m);i++)  //每行总的状态有2^m
	{
		if(i&(i<<2)) continue;  //若有曼哈顿相距为2的情况则排除
		s[state]=i;
		cnt[state++]=get_cnt(i);
	}
	for(i=0;i<state;i++)           //第0行
	{
		if(s[i]&row[0]) continue;  //row存的是不能安排士兵的情况
		dp[0][i][0]=cnt[i];
	}
	for(i=1;i<n;i++)  //每一行
		for(j=0;j<state;j++)
		{
			if(s[j]&row[i]) continue; //是否能够安排士兵
			for(k=0;k<state;k++)  //i-1行信息
			{
				if((s[j]&(s[k]>>1))||(s[j]&(s[k]<<1))) continue;//对角
				for(l=0;l<state;l++) //i-2行信息
				{
					if(s[j]&s[l]) continue;   //垂直
					dp[i][j][k]=dp[i][j][k]>dp[i-1][k][l]+cnt[j]?dp[i][j][k]:dp[i-1][k][l]+cnt[j];
				}
			}
		}
	ans=0;
	for(i=0;i<state;i++)             //枚举找到最大值
		for(j=0;j<state;j++)
			ans=ans>dp[n-1][i][j]?ans:dp[n-1][i][j];
	return ans;
}

int main()
{
	int n,m,i,j,x;

	while(scanf("%d%d",&n,&m)==2)
	{
		memset(row,0,sizeof(row));
		memset(dp,0,sizeof(dp));
		for(i=0;i<n;i++)
			for(j=0;j<m;j++)
			{
				scanf("%d",&x);
				if(!x) row[i]=(row[i]<<1)|1;  //一开始不可放士兵的位置设为1,方便后面检测
				else
					row[i]<<=1;       //可放士兵的位置不做处理
			}
		printf("%d\n",sovle(n,m));
	}
    return 0;
}


HDU ACM 4539 郑厂长系列故事——排兵布阵->状态压缩DP

标签:c   c++   acm   算法   编程   

原文地址:http://blog.csdn.net/a809146548/article/details/46406055

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!