题目描述
b 为第 i 行的状态,用 for k 来枚举
a 为第i-1行的状态,用 for j 来枚举
c 为第i-2行的状态,用 for u 来枚举
f[i][j][k] 表示在前 i 行中摆放,第 i-1 行的状态为j,第i行的状态为k,的最大值
f[i-1][u][j]表示在前i-1行中摆放,第i-2行的状态为u,第i-1行的状态为j,的最大值
然后加上第i行摆放个数cnt[b]更新最大值,此题的最后一步的为第i-2行
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
int n,m;
const int N=11,M=1<<10;
int g[110];
vector<int> state;
int cnt[M];
//滚动数组
int f[2][M][M];
int count(int x)
{
int res=0;
for(int i=0;i<m;i++)
{
res+=x>>i&1;
}
return res;
}
int check(int state)
{
for(int i=0;i<m;i++)
{
if((state>>i&1)&&((state>>i+1&1)||(state>>i+2&1)))
return 0;
}
return 1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=0;j<m;j++)
{
char c;
cin>>c;
if(c=='H')
{
g[i]+=1<<j;
}
}
}
for(int i=0;i<1<<m;i++)
{
if(check(i))
state.push_back(i);
cnt[i]=count(i);
}
//b 为第 i 行的状态,用 for k 来枚举
//a 为第i-1行的状态,用 for j 来枚举
//c 为第i-2行的状态,用 for u 来枚举
//f[i][j][k] 表示在前 i 行中摆放,第 i-1 行的状态为j,第i行的状态为k,的最大值
//f[i-1][u][j]表示在前i-1行中摆放,第i-2行的状态为u,第i-1行的状态为j,的最大值
//然后加上第i行摆放个数cnt[b]更新最大值,此题的最后一步的为第i-2行
for(int i=1;i<=n+2;i++)
{
for(int j=0;j<state.size();j++)
{
for(int k=0;k<state.size();k++)
{
for(int u=0;u<state.size();u++)
{
int a=state[j],b=state[k],c=state[u];
if((a&b)|(b&c)|(a&c))
continue;
if(g[i-1]&a | g[i]&b)
continue;
//f[i][j][k]表示在前i行中选,上一行的状态为j,
f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][u][j]+cnt[b]);
}
}
}
}
cout<<f[n+2&1][0][0];
return 0;
}