您的位置:首页 > 其它

Poj 1185 炮兵阵地 状态压缩

2014-10-14 15:22 148 查看
题目链接:http://poj.org/problem?id=1185

题目大意:

在N*M的网格地图上部署炮兵部队。地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:



如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域。炮兵的攻击范围不受地形的影响。

现在,如何部署炮兵部队,使得任何一支炮兵部队都不在其他支炮兵部队的攻击范围内,在整个地图区域内最多能够摆放多少我军的炮兵部队。

解题思路:由于每行最多只有10个位置,故状态压缩 枚举每个状态即可,同时应该 注意的是 每行的状态是由上面一行和上面两行 的状态决定的。

另外,可以知道一个位置有炮兵,则左右两个空位置不能有炮兵,因此可以先把 有效状态提取出来,然后在判断这个状态的时候,再判断这个位置是否是山地。

代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[105][70][70];  ///dp[i][j][k]:第i行为状态j,i-1行为状态k的最大放法
int sta[70];           ///合法状态数
int cot[70];           ///合法状态下本行能放的炮兵数
int map[1<<11];        ///存地图
int n,m;
int init()
{
memset(dp,0,sizeof(dp));
memset(sta,0,sizeof(sta));
memset(map,0,sizeof(map));
memset(cot,0,sizeof(cot));
}
void solve()
{
int num=(1<<m);
int ct=0;
for(int i=0;i<=num;i++)  ///枚举合法状态
if( (i&(i<<1))==0 && (i&(i<<2))==0 )///注意(i&(i<<1))==0不能写成(i&(i<<1)==0),(==优先级高于&)
sta[ct++]=i;

for(int i=0;i<ct;i++)    ///计算合法状态炮兵数
{
int cn=0;
for(int j=0;j<=m;j++)
if( sta[i]&(1<<j) ) cn++;
cot[i]=cn;
if( (map[1]|sta[i])==map[1] ) dp[1][i][0]=cn;  ///初始化第一行,零行为0
}

for(int i=2; i<=n; i++)
{
//if(map[i]==0) continue;
for(int k1=0; k1<ct; k1++)
{
if((sta[k1]|map[i-1])!=map[i-1])  continue;
for(int k2=0; k2<ct; k2++)
{
if( (sta[k2]|map[i-2])!=map[i-2] ) continue;
if( (sta[k1]&sta[k2])!=0 ) continue;
for(int j=0; j<ct; j++)
if( (sta[j]|map[i])==map[i] && (sta[j]&sta[k1])==0  && (sta[j]&sta[k2])==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);
int t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
if(m==0||n==0) {printf("0\n");continue;}
char s[12];
for(int i=1;i<=n;i++)
{
scanf("%s",s);
for(int j=0;j<m;j++)
if(s[j]=='P') map[i]=(map[i]<<1)+1;///从左往右1为P(平原),0为H(山地)
else map[i]=(map[i]<<1)+0;
}
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: