版权声明:点个关注(^-^)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
和炮兵布阵很类似,不过数据样例强一些
#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;
}