这是一道很不错的状压题
题目,数据,实现都不错
除了for循环打的头痛。。。
我们来康康这道题
首先,这是一道状压DP,因为数据量比较状压。。。
分别有N*M的地图,有缺陷的地形以及十字形的覆盖范围。
然后我们定义状态:
F[i][j][k]
用 i 表示当前枚举到第几行,j表示当前行的状态,k表示上一行的状态
因为每一行的值会受前两行的影响,上面第一行方便枚举,但是再枚举上面第一行就有点吃力,因为这样我们的值没办法保证互补干涉,导致哇(WA)掉,于是我们用本行和上一行的排列状态表示一个状态。
然后我来说说状压(毕竟我没看太懂,知道蒙蔽的痛苦(神犇们可以跳过直接看码))
我们是用一个数的二进制展开来表示状态的
比如说8表示 1000就是第一个位置选,其余不选,而每种二进制数代表不同的选择序列,用状态压缩的方式进行压缩处理,可以使用一维来代替好多维,使用时一般预处理一个“不能选的”数,它也是一个压缩过的树,用它的值来表示那个位置不可以选,而我们枚举的是一整个选择的状态,所以只要(&)后操作出现不是期望的值,就可以判定它不符合题意
1 0 0 1 0 0 1 S1
1 1 1 0 1 1 0 S2
若S2中0表示不能选,就有(s1&s2!=s1)(s1表示1的位置选择,与不能选的冲突)。
同理,当判断是否与上一行冲突时,就有(s1&s2==0)表示不冲突(即没有两列位置重合的),这样以后,就可以进行操作了。。。
康康代码
#include<bits/stdc++.h> using namespace std; int n,m,F[105],f[105][66][66],start[70],cnt=0,gs[200];//特殊记录,不爆空间 bool mp[105][30]; int main(){ cin>>n>>m; char a; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>a; if(a=='H')mp[i][j]=1;//另不能选的为1 } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ F[i]=(F[i]<<1)+mp[i][j]; //把每行“不可选”状态压缩起来方便实用 } } start[++cnt]=0; /*这个尤为重要,如果你要空间时间,就得像下面一样存 如果直接存的话,就没了(毕竟那个一整排H的数据还是有的) 不过如果从0开始循环也可以,但是放在这里起警示作用233*/ for(int i=1;i<(1<<m);i++){ if(i&(i<<1))continue; //因为左二右二不能选 if(i&(i<<2))continue; if(i&(i>>1))continue; if(i&(i>>2))continue; start[++cnt]=i;//直接存有用的就行 int x=i; while(x){ //求取每个状态的贡献 gs[cnt]++; x-=(x&(-x)); } } for(int i=1;i<=cnt;i++){ //处理第一排 if((start[i]&F[1])==0){ //不能与地形冲突 f[1][i][0]=gs[i]; } } for(int i=1;i<=cnt;i++){ //第二排 if((start[i]&F[2])==0) for(int j=1;j<=cnt;j++){ if((start[i]&start[j])==0&&(start[j]&F[1])==0){ //判断是否冲突 f[2][i][j]=gs[j]+gs[i]; } } } //让for来的更猛烈些吧(枚举状态) for(int i=3;i<=n;i++){ for(int j=1;j<=cnt;j++){ //当前一排状态 if((start[j]&F[i])==0){ for(int k1=1;k1<=cnt;k1++){ //上面第一排 if((start[j]&start[k1])==0&&(start[k1]&F[i-1])==0){ for(int k2=1;k2<=cnt;k2++){ //上面第二排 if((start[j]&start[k2])==0&&(start[k1]&start[k2])==0&&(start[k2]&F[i-2])==0){ //判断所有冲突情况 f[i][j][k1]=max(f[i][j][k1],f[i-1][k1][k2]+gs[j]);//从之前转移过来就行 } } } } } } } int ans=0; //所有的值都在最后1排存,用这一排的所有情况的最大值当最大值 for(int i=1;i<=cnt;i++){ for(int j=1;j<=cnt;j++){ ans=max(ans,f[n][i][j]); } } cout<<ans; }
于是,这个就完了
里面的状态转移还好说,这个判断冲突搞得我掉头发。。
就这样吧,
马蜂一般,希望能帮到您