一道非常有意思的题目 很久之前考过 但那时候好像只会打裸搜索(捂脸跑
后来看题解的时候也是没有学状压的所以算是闲置了很久没动的题
昨天看到的时候第一反应是m<=10所以压m然后跑1-n枚举每一行
但是非常遗憾的是我一直在想横行怎么判断合法 所以比较sb的我想了好久都没想出来
于是又很怂逼地去看了题解(我怎么这么怂
横行合法只要位移然后与一下就可以判断了 竖行的合法就是根据上面两行的状态转移
f[i][j][k]表示的是第i行上一行状态为j本行状态为k的炮塔数量
特别注意零也是一种情况!!!昨天被坑了今天又被坑了TAT
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<string> using namespace std; ],f[][][],b[],sum[]; bool pd(int x){//横行是否合法 )) ; )) ; ; } int w(int x){//判断此状态炮塔个数 ; ){ ) sum++; } return sum; } int main(){ memset(f,,sizeof(f)); int n,m; scanf ("%d%d",&n,&m); ;i<=n;++i) ;j<=m;++j){ char ch; cin>>ch; <<j-;//记录是否可放 } ; ;i<=(<<m)-;++i) if (pd(i)) b[++tot]=i,sum[tot]=w(i);//!!0也是一种放法!! ;i<=tot;++i) ]&b[i])) f[][][i]=sum[i]; ;i<=n;++i) ;j<=tot;++j){ if (!(b[j]&g[i])){//此行可以放 ;k<=tot;++k){ if (!(b[k]&b[j])){ ;l<=tot;++l) if (!(b[l]&b[j])){//前两行无影响 ][l][k]!=-) f[i][k][j]=max(f[i][k][j],f[i-][l][k]+sum[j]);//转移 } } } } } ; ;i<=tot;++i) ;j<=tot;++j) ans=max(ans,f[n][i][j]); cout<<ans; ; }