裸状压
正常状压只需要枚举上一行即可,但是这道题我们需要枚举上两行,这样才能保证不冲突,合法的状态时i&(i<<1)=0,i&(i<<2)=0,我们只需要考虑它和他左边不冲突就好了,右边会有下一个位置保证和他不冲突,于是这道题就没了,需要滚动一下数组
代码
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
char map[105][105];
int e[1050],s[1050],t[1050],f[2][1050][1050],cnt;
inline void dfs()
{
int su=1<<m;
for (int i=0;i<su;i++)
if (!(i&(i<<1))&&!(i&(i<<2)))
{
s[++cnt]=i;int k=i;
while (k) t[cnt]+=(k&1),k>>=1;
}
return ;
}
inline bool che(int x,int y)
{
return (s[x]&e[y])==0;
}
signed main()
{
scanf("%d%d",&n,&m);dfs();
for (int i=1;i<=n;i++) scanf("%s",map[i]+1);
for (int i=1;i<=n;i++)
for (int k=1;k<=m;k++)
if (map[i][k]=='H') e[i]+=(1<<(m-k));
int x=1,y=0;
for (int i=1;i<=cnt;i++)
if (che(i,1)) f[x][i][1]=t[i];
swap(x,y);
for (int i=1;i<=cnt;i++)
if (che(i,2))
for (int k=1;k<=cnt;k++)
if (che(k,1)&&!(s[i]&s[k]))
f[x][i][k]=t[i]+t[k];
for (int i=3;i<=n;i++)
{
swap(x,y);
for (int k=1;k<=cnt;k++)
if (che(k,i))
for (int j=1;j<=cnt;j++)
if (!(s[k]&s[j])&&che(j,i-1))
for (int h=1;h<=cnt;h++)
if (!(s[h]&s[j])&&!(s[h]&s[k])&&che(h,i-2))
f[x][k][j]=max(f[x][k][j],f[y][j][h]+t[k]);
}
int ans=0;
for (int i=1;i<=cnt;i++)
for (int k=1;k<=cnt;k++)
ans=max(ans,f[x][i][k]);
cout<<ans;
return 0;
}