可比百分 @ 2018-11-07 17:17:33
刚学状压……(空间还没有用滚动数组优化,但是其他点也都错了……)
#include<iostream>
#include<cstdio>
#define S 1030
#define N 110
using namespace std;
int dp[N][S][S];
int a[N][N],can[N][S],sum[S],b[S];
int n,m,maxstate;
int main()
{
cin>>n>>m;
maxstate=(1<<m)-1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
char x;
int p;
cin>>x;
if(x=='P')
p=0;
else
p=1;
b[i]<<=1;
b[i]+=p;
}
for(int i=1;i<=n;i++)
for(int j=0;j<=maxstate;j++)
{
if(((j<<1)&j)!=0) continue;
if(((j<<2)&j)!=0) continue;
int flag=1;
if(b[i]&j) flag=0;
if(flag) can[i][j]=1;
}
for(int i=0;i<=maxstate;i++)
{
int ss=i;
while(ss)
{
if(ss%2) sum[i]++;
ss/=2;
}
}
for(int j=0;j<=maxstate;j++)
{
if(!can[1][j]) continue;
for(int k=0;k<=maxstate;k++)
dp[1][k][j]=sum[j];
}
for(int i=0;i<=maxstate;i++)
{
if(!can[1][i]) continue;
for(int j=0;j<=maxstate;j++)
{
if(!can[2][j]) continue;
if((i&j)!=0) continue;
dp[2][i][j]=sum[i]+sum[j];
}
}
for(int i=3;i<=n;i++)
for(int j=0;j<=maxstate;j++)//枚举上一行状态
{
if(!can[i-1][j]) continue;
for(int k=0;k<=maxstate;k++)//枚举本行状态
{
if(!can[i][k]) continue;
if((j&k)!=0) continue;
for(int t=0;t<=maxstate;t++)//枚举上两行状态
{
if(!can[i-2][j]) continue;
if((j&t)!=0 || (k&t)!=0)continue;
dp[i][j][k]=max(dp[i][j][k],dp[i-1][t][j]+sum[k]);
}
}
}
int ans=0;
for(int j=0;j<=maxstate;j++)
for(int k=0;k<=maxstate;k++)
ans=max(ans,dp[n][j][k]);
cout<<ans;
return 0;
}