hdu4539 郑厂长系列故事——排兵布阵 状压dp

版权声明:点个关注(^-^)V https://blog.csdn.net/weixin_41793113/article/details/89716891

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4539

Problem Description

  郑厂长不是正厂长
  也不是副厂长
  他根本就不是厂长
  事实上
  他是带兵打仗的团长

  一天,郑厂长带着他的军队来到了一个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

扫描二维码关注公众号,回复: 6086141 查看本文章

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

Source

2013腾讯编程马拉松复赛第二场(3月30日)

和炮兵布阵很类似,不过数据样例强一些

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,m;
int ch[105][15],dp[4][1<<10][1<<10],state[1<<10],sum[1<<10],F[105];

int cal(int x){
    int ans = 0;
    while(x>0){
        ans++;
        x-=x&(-x);
    }
    return ans;
}

int main(){
    ios::sync_with_stdio(false);
    while(cin>>n>>m){
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                cin>>ch[i][j];//可以不用开ch[][]数组,用一个int代替就好
                F[i]<<=1;
                if(!ch[i][j]) F[i]+=1;//0标记为1,F[i]记录第i行不能放的状态
            }

        int tot = (1<<m)-1;
        int cnt = 0;
        for(int i=0;i<=tot;i++)
            if(!(i & (i<<2)) && !(i & (i>>2)))//预处理出本行不会冲突的状态
                state[++cnt] = i;

        for(int i=1;i<=cnt;i++)
            sum[i] = cal(state[i]);//预处理每个状态的士兵个数


        for(int i=1;i<=cnt;i++){//其实这可以不写
            if(state[i] & F[1])
                continue;
            dp[1][i][1] = sum[i];//写1不写0方便遍历
        }

        for(int i=1;i<=cnt;i++)
            for(int j=1;j<=cnt;j++){
                if(state[i] & F[2])
                    continue;
                if(state[j] & F[1])
                    continue;
                if(((state[i]<<1) & state[j]) || ((state[i]>>1) & state[j]))
                    continue;
                dp[2][i][j] = sum[i]+sum[j];
        }

        for(int i=3;i<=n;i++)
            for(int j=1;j<=cnt;j++){
                if(state[j] & F[i])
                    continue;
                for(int k=1;k<=cnt;k++){
                    if(state[k] & F[i-1])
                        continue;
                    if(((state[j]<<1) & state[k]) || ((state[j]>>1) & state[k]))//左右<<都写写,鬼知道有什么花样
                        continue;
                    for(int p=1;p<=cnt;p++){
                        if(state[p] & F[i-2])
                            continue;
                        if(state[j] & state[p])
                            continue;
                        if(((state[k]<<1) & state[p])||((state[k]>>1) & state[p]))
                            continue;
                        dp[i%3][j][k] = max(dp[i%3][j][k],dp[(i-1)%3][k][p]+sum[j]);
                    }
                }
            }

        int ans = 0;
        for(int i=1;i<=cnt;i++)
            for(int j=1;j<=cnt;j++)
                ans = max(ans,dp[n%3][i][j]);

        cout<<ans<<endl;
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41793113/article/details/89716891