poj 1185 状态压缩dp(炮兵阵地)

题意:司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示)。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一个炮兵部队攻击到的区域:沿横向左右各两格,沿纵向上下各两格。炮兵的攻击范围不受地形的影响。 现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

思路:dp[i][j][k]表示第i行布局为j,第i-1行布局为k时,前i行的最多炮兵数目。1、j,k这两种布局必须相容。否则 dp[i][j][k] = 0;2、 dp[i][j][k] = max{dp[i-1][k][m], m = 0...1023} + Num(j),Num(j)为布局j中炮兵的数目,且j和m必须相容。此时满足无后效性。

初始条件:
dp[0][j][0] = Num(j)
dp[1][i][j] = dp[0][j][0] + Num(i);

这样一来需要开100*1024*1024大的数组,不能承受。注意到每一行里最多能放4个炮兵。就算全是平地,能放炮兵的方案数目也不超过 60 (用一遍dfs可以全部求出)。算出一行在全平地情况下所有炮兵的排列方案,存入数组state[65],那么int dp[100][70][70] 足矣。

#include 
#include 
#include 
using namespace std;
#define N 105
#define M 65
int n,m,mm;
int state[65],w[65],num = 0;
int dp[N][M][M],t[105];
char s[105][15];
int flag[15];
void dfs(int d){
    int i,j = 0,sum=0;
    if(d == m){
        for(i = 0,j=m-1;j>=0;j--){
            i <<= 1;
            if(flag[j] == 1){
                i++;
                sum++;
            }
        }
        state[num] = i;
        w[num++] = sum;
        return ;
    }
    dfs(d+1);
    if((d>=2&&!flag[d-1]&&!flag[d-2])||(d==1&&!flag[d-1])||!d){//因为两个大炮之间至少隔两个地方不能放东西
        flag[d] = 1;
        dfs(d+1);
        flag[d] = 0;
    }
}
int main(){
    int i,j,k,a,res=0;
    scanf("%d %d",&n,&m);
    for(i = 0;i


你可能感兴趣的:(动态规划——位运算(状态压缩))