HDU 4539 经典状态压缩DP

来源:互联网 发布:域名能绑定端口吗 编辑:程序博客网 时间:2024/06/05 17:51

经典状态压缩DP

题意:

一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
  根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
  现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。

Input

输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。

Output

请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。

Sample Input

6 60 0 0 0 0 00 0 0 0 0 00 0 1 1 0 00 0 0 0 0 00 0 0 0 0 00 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;                    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;}
原创粉丝点击