题目:炮兵阵地
思路:位运算+记忆化搜索
注意:记忆化时要存2个状态
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;
#define maxn 100
#define maxm 10
int n,m;
int a[maxn]={0};
int b[1<<maxm]={0};
int f[1<<maxm][1<<maxm][maxn]={0};
int judge(int x){
if(x&(x<<1)||x&(x<<2)||x&(x>>1)||x&(x>>2)) return -1; //左右不能放
int y=x,t=0,s=0; //预处理出每种状态下炮兵的个数
while(y){
t=y&1;
if(t==1) s++;
y>>=1;
}
return s;
}
int dfs(int step,int state1,int state2){
if(step==n){
return 0;
}
int ans=0;
for(int i=0;i<(1<<m);i++){
if(b[i]!=-1&&!(i&state1)&&!(i&state2)&&(i|a[step])==a[step]){ //不能被上方的炮误伤且只能放在平原
int x;
if(f[state2][i][step]) x=f[state2][i][step];
else x=f[state2][i][step]=dfs(step+1,state2,i);
ans=max(ans,b[i]+x);
}
}
return ans;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
string x;
cin>>x;
for(int j=0;j<m;j++){
bool y;
if(x[j]=='P') y=true;
else y=false;
a[i]=a[i]*2+y; //处理地图
}
}
for(int i=0;i<(1<<m);i++){
b[i]=judge(i);
}
printf("%d",dfs(0,0,0));
return 0;
}