标签:eof 个数 class return 意思 names set span name
一道非常有意思的题目 很久之前考过 但那时候好像只会打裸搜索(捂脸跑
后来看题解的时候也是没有学状压的所以算是闲置了很久没动的题
昨天看到的时候第一反应是m<=10所以压m然后跑1-n枚举每一行
但是非常遗憾的是我一直在想横行怎么判断合法 所以比较sb的我想了好久都没想出来
于是又很怂逼地去看了题解(我怎么这么怂
横行合法只要位移然后与一下就可以判断了 竖行的合法就是根据上面两行的状态转移
f[i][j][k]表示的是第i行上一行状态为j本行状态为k的炮塔数量
特别注意零也是一种情况!!!昨天被坑了今天又被坑了TAT
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<string> 7 using namespace std; 8 int g[200],f[200][200][200],b[200],sum[200]; 9 bool pd(int x){//横行是否合法 10 if (x&(x<<1)) return 0; 11 if (x&(x<<2)) return 0; 12 return 1; 13 } 14 int w(int x){//判断此状态炮塔个数 15 int sum=0; 16 for (int l=x;l;l>>=1){ 17 if (l&1) sum++; 18 } 19 return sum; 20 } 21 int main(){ 22 memset(f,255,sizeof(f)); 23 int n,m; 24 scanf ("%d%d",&n,&m); 25 for (int i=1;i<=n;++i) 26 for (int j=1;j<=m;++j){ 27 char ch; 28 cin>>ch; 29 if (ch==‘H‘) g[i]|=1<<j-1;//记录是否可放 30 } 31 int tot=0; 32 for (int i=0;i<=(1<<m)-1;++i) if (pd(i)) b[++tot]=i,sum[tot]=w(i);//!!0也是一种放法!! 33 for (int i=1;i<=tot;++i) if (!(g[1]&b[i])) f[1][1][i]=sum[i]; 34 for (int i=2;i<=n;++i) 35 for (int j=1;j<=tot;++j){ 36 if (!(b[j]&g[i])){//此行可以放 37 for (int k=1;k<=tot;++k){ 38 if (!(b[k]&b[j])){ 39 for (int l=1;l<=tot;++l) 40 if (!(b[l]&b[j])){//前两行无影响 41 if (f[i-1][l][k]!=-1) f[i][k][j]=max(f[i][k][j],f[i-1][l][k]+sum[j]);//转移 42 } 43 } 44 } 45 } 46 } 47 int ans=-1; 48 for (int i=1;i<=tot;++i) for (int j=1;j<=tot;++j) ans=max(ans,f[n][i][j]); 49 cout<<ans; 50 return 0; 51 }
标签:eof 个数 class return 意思 names set span name
原文地址:http://www.cnblogs.com/YZSTUDIO/p/6444038.html