Belarus @ 2019-08-24 15:50:04
#include<bits/stdc++.h>
using namespace std;
const int maxn=102,maxm=11;
int n,m,a[maxn],f[3][(1<<maxm)-1][(1<<maxm)-1],ans;
inline int count(int x){
int cnt=0;
for(int i=m-1;i>=0;i--) if((x>>i)&1) cnt++;
return cnt;
}
inline bool valid(int row,int x){
if(x&(x>>1)) return false;
if(x&(x>>2)) return false;
if(x&(x<<1)) return false;
if(x&(x<<2)) return false;
else for(int i=m-1;i>=0;i--){
if(((x>>i)&1)&&(!((a[row]>>i)&1)))
return false;
}
return true;
}
int main(){
ios::sync_with_stdio(0);
memset(f,-0x3f,sizeof(f));
cin>>n>>m;
char c;
for(int i=1;i<=n;i++)
for(int j=0;j<m;j++){
cin>>c;
while(c!='P' && c!='H')
cin>>c;
if(c=='P') a[i]|=(1<<j);
}
f[0][0][0]=0;
for(int j=0;j<(1<<m);j++)
if(valid(1,j))
f[1][j][0]=count(j);
for(int i=2;i<=n;i++)
for(int j=0;j<(1<<m);j++)
if(valid(i,j))
for(int k=0;k<(1<<m);k++)
if((k&j)==0)
if(valid(i-1,k))
for(int l=0;l<(1<<m);l++)
if((j&l)==0)
f[i%3][j][k]=max(f[i%3][j][k],f[(i-1)%3][k][l]+count(j));
for(int j=0;j<(1<<m);j++)
if(valid(n,j))
for(int k=0;k<(1<<m);k++)
if((k&j)==0)
if(valid(n-1,k))
ans=max(ans,f[n%3][j][k]);
cout<<ans;
return 0;
}
by kcn999 @ 2019-08-24 15:56:25
@Charleyxiao 预处理可行方案
by Belarus @ 2019-08-24 15:57:32
@kcn999 试过了,更慢(用递归写的)
by kcn999 @ 2019-08-24 15:57:40
也就是先把所有valid
返回值为true
的状态记录下来,然后再dp。
by 小小小朋友 @ 2019-08-24 15:57:55
这什么玩意儿……
by kcn999 @ 2019-08-24 15:58:26
@Charleyxiao 不是直接枚举就好了嘛,问什么要递归。。。
by End_donkey @ 2019-08-24 15:58:34
预处理再判断
by 小小小朋友 @ 2019-08-24 15:58:34
楼上的楼上正解
by Belarus @ 2019-08-24 16:00:41
@kcn999 谢谢
by kcn999 @ 2019-08-24 16:03:50
@Charleyxiao 好吧,其实我说的不是很清楚。先预处理出对于每一行,不考虑其他行的影响,只看当前行内是否可行的所有状态,然后dp的时候再判断是否在其他行的影响下不可行
by 吃饭且睡觉66 @ 2019-08-24 16:16:35
开o2试试