您的位置:首页 > 其它

Hdu 4539 郑厂长系列故事——排兵布阵 状态压缩

2014-10-14 18:08 211 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4539

题目大意:一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。

现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。

解题思路:和上一道炮兵阵地 一样的处理,只是判状态注意一下;

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[105][180][180]; // dp[i][j][k]  表示第i行第j个状态,第i-1行第k个状态的最大值
int sta[180];  //合法的状态
int cot[180];  //每个合法状态的炮兵数
int map[1<<11];  //山地的位置
int n,m;
void init()
{
memset(dp,-1,sizeof(dp));  //此处 初始化为-1,下面 的状态转移 可以剪枝,特别注意
memset(sta,0,sizeof(sta));
memset(cot,0,sizeof(cot));
memset(map,0,sizeof(map));
}
void solve()
{
int num=(1<<m),ct=0;

for(int i=0;i<num;i++)  //筛选每行的合法状态
if( (i&(i<<2))==0  )
sta[ct++]=i;

for(int i=0;i<ct;i++)
{
int cnt=0;
for(int j=0;j<m;j++)
if( sta[i]&(1<<j) )  //判断每个合法状态能放的炮兵数
cnt++;

if( (map[1]&sta[i]) == 0 )//初始化  第一行状态
dp[1][i][0]=cnt;

cot[i]=cnt;
}

for(int i=2; i<=n; i++)  //枚举行数
for(int k1=0; k1<ct; k1++)  //枚举上一行状态
for(int k2=0; k2<ct; k2++)  //枚举上两行状态
if(dp[i-1][k1][k2]>=0)   //可能出现0状态,所以要>=0
for(int j=0; j<ct; j++)   //枚举当前行状态
if( (sta[j]&(sta[k1]<<1))==0 && (sta[j]&(sta[k1]>>1))==0 && (sta[j]&sta[k2])==0 && (map[i]&sta[j])==0 )
dp[i][j][k1]=max( dp[i][j][k1],dp[i-1][k1][k2]+cot[j]);
int ans=0;
for(int i=0; i<ct; i++)
for(int j=0; j<ct; j++)
ans=max(dp
[i][j],ans);
printf("%d\n",ans);
}
int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
init();
int a;
for(int i=1; i<=n; i++)
for(int j=0; j<m; j++)
{
scanf("%d",&a);
if(a==0) map[i]=(map[i]<<1)+1;
else map[i]=(map[i]<<1)+0;
}
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: