HDU - 4539 郑厂长系列故事——排兵布阵 ( 状压DP )

题意:

每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。 
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。 

分析:

因为涉及两行,往常一行的话就直接开个二维的就可以,但现在是两行,所以多加一维即可。其他的还跟往常一样的思路。

#include<bits/stdc++.h>

using namespace std;

const int maxn=170;

int dp[102][maxn][maxn];
int n,m;
int g[maxn];
int s[maxn];
int c[maxn];
int cnt;

int mycount(int x){
    int res=0;
    while(x){
        if(x&1) res++;
        x>>=1;
    }
    return res;
}

int main(){

    while(scanf("%d%d",&n,&m)!=EOF){
        memset(g,0,sizeof g);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                int tmp;
                scanf("%d",&tmp);
                if(!tmp){
                    g[i]|=(1<<j);
                }
            }
        }
        cnt=0;
        for(int i=0;i<(1<<m);i++){
            if(i&(i<<2)) continue;
            s[cnt]=i;
            c[cnt++]=mycount(i);
        }
        memset(dp,0,sizeof dp);
        for(int i=0;i<n;i++){
            for(int j=0;j<cnt;j++){
                if(i==0){
                    if(g[i]&s[j]) continue;
                    dp[0][j][0]=c[j];
                    continue;
                }
                if(g[i]&s[j]) continue;
                for(int k=0;k<cnt;k++){
                    if((s[j]&(s[k]<<1))||(s[j]&(s[k]>>1))) continue;
                    for(int l=0;l<cnt;l++){
                        if(s[j]&s[l]) continue;
                        if((s[k]&(s[l]<<1))||(s[k]&(s[l]>>1))) continue;
                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+c[j]);
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;i<cnt;i++){
            for(int j=0;j<cnt;j++){
                ans=max(ans,dp[n-1][i][j]);
            }
        }
        printf("%d\n",ans);
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值