您的位置:首页 > 其它

HDU 4539 经典状态压缩DP

2017-08-18 00:48 453 查看

经典状态压缩DP

题意:

一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。

  根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为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


思路:

​ 此题和POJ1185 基本一致,只是建立状态的时候会有些迷惑。

哈密顿距离为2:距离某一个位置的横纵长度和为2



对于此题条件如图所示:炮弹能打击的位置,就是不能发生冲突的条件,解法如POJ1185.

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int n,m;
int map[105];
int num[205];
int state[205];
int dp[105][205][205];

int main(int argc, char const *argv[])
{
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m) != EOF) {
memset(dp,0,sizeof(dp));
memset(state,0,sizeof(state));
memset(num,0,sizeof(num));
memset(map,0,sizeof(map));

for(int i = 0;i < n; i++) {
int c;
for(int j = 0;j < m; j++) {
scanf("%d",&c);
if(c == 0) map[i] += (1<<j);
}
}
int pos = 0;
for(int i = 0;i < (1<<m); i++) {
if(i&(i<<2)) continue;
state[pos] = i;
int k = i;
int Number = 0;
while(k) {
if(k&1) Number++;
k >>= 1;
}
num[pos++] = Number;
}
for(int i = 0;i < pos; i++) {
if(state[i]&map[0]) continue;
dp[0][i][0] = num[i];
}
for(int i = 0;i < pos; i++) {
if(state[i]&map[1]) continue;
for(int j = 0;j < pos; j++) {
if(state[j]&map[0]) continue;
if((state[i]<<1)&state[j]) continue;
if((state[i]>>1)&state[j]) continue;
dp[1][i][j] = max(dp[1][i][j],dp[0][j][0] + num[i]);
}
}
for(int r = 2;r < n; r++) {
for(int i = 0;i < pos; i++) {
if(state[i]&map[r]) continue;
for(int j = 0;j < pos; j++) {
if(state[j]&map[r-1]) continue;

4000
if((state[i]<<1)&state[j]) continue;
if((state[i]>>1)&state[j]) continue;

for(int k = 0;k < pos; k++) {
if(state[k]&map[r-2]) continue;

if((state[j]<<1)&state[k]) continue;
if((state[j]>>1)&state[k]) continue;
if(state[i]&state[k]) continue;
dp[r][i][j] = max(dp[r][i][j],dp[r-1][j][k] + num[i]);
}
}
}
}
int ans = 0;
for(int i = 0;i < pos; i++) {
for(int j = 0;j < pos; j++) {
ans = max(ans,dp[n-1][i][j]);
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  压缩 dp