分析:首先我们可以先预处理一行中出所有状态中哪那些状态是可行的,即炮兵不会被放在另一个炮兵的射程内用each数组存储。然后同样预处理出地图每一行的状态,其中高地用1表示,用mp数组存储,这两个数组是我为了判断在第j行中第i个状态是否可行,即each[i]&mp[j],返回1表示有 冲突
然后我们用dp[I][j][k]来表示在第i行中的第j个状态与第n-1行中的第k个状态中炮兵的数量,然后预处理出第1,2行,然后就可以写出状态转移方程了
dp[I][j][k]=max(dp[I-1][k][kk])其中j表示第I行的状态,k表示第i-1行的状态,kk表示第i-2行的状态,且这三行中的状态与地图没有冲突,两两对应的状态也没有冲突。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e5+10;
char ch[105][15];
ll dp[105][65][65];
int each[65];//each[i]表示每一行中合理的不产生冲突的状态
int sum[65];//表示第i种状态中炮兵(即1)的数量
int mp[105];//表示每一行中地图的状态,高地(H)为1
int n,m;
bool judge(int s){//判断s这个状态是否符合题意(即不互相攻击)
for (int i=0;i<m;){
if (s&(1<<i)){
if (i+1<m&&(s&(1<<(i+1))))return false;
if (i+2<m&&(s&(1<<(i+2))))return false;
i+=2;
}else i++;
}
return true;
}
bool judge_map(int row,int s){//s这个状态在第row行是否可行,返回1表示不可行,因为炮兵放在高地了
return (mp[row]&s);
}
int main()
{
while (scanf ("%d%d",&n,&m)!=EOF){
for (int i=1;i<=n;i++){
scanf ("%s",ch[i]+1);
mp[i]=0;
for (int j=1;j<=m;j++){
if (ch[i][j]=='H'){
mp[i]+=(1<<(j-1));
}
}
}
memset (dp,0,sizeof (dp));
int cnt=0;
for (int i=0;i<(1<<m);i++){//预处理出每一行可行的状态数
if (judge(i))each[cnt++]=i;
}
for(int i=0;i<cnt;i++){//与处理出每一种状态的炮兵数
sum[i]=0;
for (int j=0;j<m;j++){
if (each[i]&(1<<j)){
sum[i]++;
}
}
}
for(int i=0;i<cnt;i++){//预处理第一行
if (!judge_map(1,each[i])){
dp[1][i][0]=sum[i];
}
}
for(int i=0;i<cnt;i++){//第二行
if (judge_map(2,each[i]))continue;
for (int j=0;j<cnt;j++){
if (!(each[i]&each[j])){//这两行对应的状态没有冲突
dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+sum[i]);
}
}
}
for (int i=3;i<=n;i++){
for (int j=0;j<cnt;j++){//第i行的状态
if (judge_map(i,each[j]))continue;
for (int k=0;k<cnt;k++){//第n-1行的状态
if (judge_map(i-1,each[k])) continue;
if ((each[j]&each[k]))continue;//i行与 i-1行冲突
for (int kk=0;kk<cnt;kk++){//第n-2行的状态
if (judge_map(i-2,each[kk]))continue;
if (each[k]&each[kk])continue;//i-1行与i-2冲突
if (each[j]&each[kk])continue;//i行与i-2行冲突
dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][kk]+sum[j]);
}
}
}
}
ll ans=0;
for (int i=0;i<cnt;i++){
for (int j=0;j<cnt;j++){
ans=max(ans,dp[n][i][j]);
}
}
printf ("%lld\n",ans);
}
return 0;
}