您的位置:首页 > 其它

poj1185 炮兵阵地(状压dp)

2016-07-16 11:52 295 查看
炮兵阵地

Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 24753Accepted: 9551
Description司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用”H” 表示),也可能是平原(用”P”表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:



如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

Input第一行包含两个由空格分割开的正整数,分别表示N和M;

接下来的N行,每一行含有连续的M个字符(‘P’或者’H’),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。Output仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。Sample Input5 4
PHPP
PPHH
PPPP
PHPP
PHHPSample Output6

这道题需要自己好好想想,推一推状态方程。
为什么是这样子?
状态方程如下:
int &t=dp[i][l][j];
t=max(t,dp[i-1][j][k]+coun[l]);
为什么是这样?
因为炮的射程有两格,所以我们应该使用三维,第一维表示哪一行,第二维表示第一格射程,第三维表示第二格射程。
所以我们的dp数组应该是dp[101][(1

if((i&j)^i)
return true;
return false;`


事实上我开始犯了这样一个错误,我写的是

if((i&j)^j)return true;
return false;


这样子判断的是j是否在i状态中,这个需要仔细想一下。。。

然后就是代码了:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#include<vector>
#define cls(x,y) memset((x),(y),sizeof((x)));
const int maxn=105;
const int maxm=15;
const int maxk=(1<<10)+1;
char a[maxn][maxm];
int dp[maxn][maxn][maxn];
int val[maxn];
int n,m;
bool used[maxm];
int nums,coun[maxk],sta[maxk];

bool J(int j) {
if(((j<<1)&j)||((j<<2)&j))return false;
return true;
}
bool F(int s,int t) {
if(s&t)return false;
return true;
}
bool f(int i,int j) {
if((i&j)^i)return true;
return false;
}
void work() {
cls(dp,0)
nums=0;
for(int i=0; i<(1<<m); ++i) {
if(!J(i))continue;
sta[nums]=i;
int t=0,fl=i;
while(fl) {
++t;
fl&=fl-1;
}
coun[nums++]=t;
}
int ans=0;
for(int i=0; i<nums; ++i) {
//        cout<<sta[i]<<" "<<val[1]<<endl;
if(f(sta[i],val[1]))continue;
//        cout<<sta[i]<<" "<<val[1]<<" "<<coun[i]<<endl;
int &t=dp[1][i][0];
t=max(t,coun[i]);
ans=max(ans,t);
}
for(int i=2; i<=n; ++i) {
for(int j=0; j<nums; ++j) {//force i-1
if(f(sta[j],val[i-1]))continue;
for(int k=0; k<nums; ++k) {//force i-2
if((sta[j]&sta[k])||f(sta[k],val[i-2]))continue;
for(int l=0; l<nums; ++l) {//force i
if((sta[l]&sta[k])||(sta[l]&sta[j])||(f(sta[l],val[i])))continue;
int &t=dp[i][l][j];
t=max(t,dp[i-1][j][k]+coun[l]);
ans=max(ans,t);
}
}
}
}
printf("%d\n",ans);
}

int main() {
#ifdef tangge
freopen("1185.txt","r",stdin);
#endif // tangge
while(~scanf("%d%d",&n,&m)) {
getchar();
#ifdef tangge
if(!n&&!m)break;
#endif // tangge
for(int i=1; i<=n; ++i)scanf("%s",a[i]);
cls(val,0)
for(int i=1; i<=n; ++i) {
for(int j=0; j<m; ++j) {
val[i]=(val[i]<<1)+(a[i][j]=='P');
}
}
work();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: