这道题用DP做有两种解法,一是三进制表示,我认为这种应该是比较理想的,但是比较难写。
另一种就是二进制,不过需要注意的是,每一行的状态最多只有60种,所以60*60*60*100加上一些剪枝勉强可以过= =
用dp[i][j][k]表示第i行,上一行的状态是j,这一行的状态是k。则转移到下一行时有,dp[i+1][k][l]=max(dp[i+1][k][l], dp[i][j][k]+popcount[l])
注意不要用map,vector什么的,很容易就超时了= =
#include <cstdio>
#include <cstring>
int n,m,tot,ans;
char mmp[15];
int mp[105];
int dp[105][65][65];
int dic[65];
int popcount[65];
inline int max(int a, int b) {return a>b?a:b;}
int main()
{
while (scanf("%d%d",&n,&m)==2)
{
tot=0;
for (int i=0;i<(1<<m);i++)
{
if ((i&(i<<1)) || (i&(i<<2))) continue;
int tmp=i; popcount[tot]=0;
while (tmp) {popcount[tot]+=(tmp&1); tmp>>=1;}
dic[tot]=i; tot++;
}
for (int i=1;i<=n;i++)
{
scanf("%s",mmp);
mp[i]=0;
for (int j=0;j<m;j++) mp[i]=mp[i]<<1|(mmp[j]=='H');
}
memset(dp,-1,sizeof(dp));
for (int i=0;i<tot;i++)
{
if (dic[i]&mp[1]) continue;
dp[1][0][i]=popcount[i];
}
for (int i=1;i<=n;i++)
for (int j=0;j<tot;j++)
for (int k=0;k<tot;k++)
{
if (dic[j]&dic[k]) continue;
int x=mp[i]|dic[j]|dic[k];
for (int l=0;l<tot;l++)
{
if (dic[l]&x) continue;
if (dp[i-1][j][k]==-1) continue;
dp[i][k][l]=max(dp[i][k][l],dp[i-1][j][k]+popcount[l]);
//printf("%d %d %d %d\n",i,dic[k],dic[l],dp[i][k][l]);
}
}
ans=0;
for (int i=0;i<tot;i++)
for (int j=0;j<tot;j++)
ans=max(ans,dp[n][i][j]);
printf("%d\n",ans);
}
return 0;
}