AcWing 292. 炮兵阵地
原题链接
中等
//行内必须相容,每一行和上一行,上上一行必须相容
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[105],cnt[105];//a存储所有可能的状态,cnt存储该状态下能安放炮车的数目(二进制表示下1的数目)
int f;
int dp[105][65][65];//第i行状态为j,i-1行状态为k
int g[105];//每一行状态的10进制表示
//把十进制在二进制表示下的1代表此处安放大炮
bool ok(int x)//判断这种状态是否成立
{
if(x&(x<<1)) return 0;
if(x&(x<<2)) return 0;
return 1;
}
int get1(int x)//获取x二进制表示下1的数目
{
int j=0;
while(x)
{
if(x&1) j++,x/=2;
else x/=2;
}
return j;
}
void init()//存储所以可能成立的状态以及该种状态下1的数目
{
for(int i=0;i<1<<m;i++)
if(ok(i)) a[++f]=i,cnt[f]=get1(i);
}
int main()
{
string s;
cin>>n>>m;
init();
for(int i=1;i<=n;i++)
{
cin>>s;
for(int j=0;j<s.size();j++)
{
if(s[j]=='H')
g[i]+=1<<j;//把山地看做1,用十进制存储每行原来的状态
}
}
int ans=0;
for(int i=1;i<=n;i++)//每一行
{
for(int j=1;j<=f;j++)//这一行的状态
{
for(int k=1;k<=f;k++)//上一行的状态
{
for(int l=1;l<=f;l++)//上上一行的状态
{
int x=a[j],y=a[k],z=a[l];
if((x&y)||(x&z)||(x&g[i])) continue;//与前两行和地形必须相容
dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+cnt[j]);//满足条件就更新第i行的值
ans=max(ans,dp[n][j][k]);
}
}
}
}
cout<<ans<<endl;
}