<状压DP>codevs 2451 互不侵犯
2017-10-12 16:41
375 查看
题面的链接
有点像八皇后,嗯,但是并不一样。
把每一行可以放的国王的情况压缩成二进制数,有国王用1表示,没有国王用0表示。
①预处理在一行之内合法的情况。也就是不能有相邻的1。
听说正解是用dfs跑的,我直接打了一个for循环。n最大只有9,状态数最多有2^9,不会超时。每种状态存在exist数组里
②预处理哪两种状态是可以挨着的,也就是上下两行可以同时存在的状态。同样记在一个数组里。上一个预处理时,可以把状态存到数组里,然后直接调用下标。存can数组
③同时,还要记录一下每一种状态的国王的数量,记为cnt数组。
④dp数组:dp[i][j][pos]表示放到第i行,已经放了j个国王,这一行的状态的下标为pos时的方案数。转移时,枚举上一行的状态,累加。即:dp[i][j][pos]=Σdp[i-1][j-cnt[pos]][k],其中,k为枚举的上一层的状态的下标
⑤注意数据范围要开long long
代码:
有点像八皇后,嗯,但是并不一样。
把每一行可以放的国王的情况压缩成二进制数,有国王用1表示,没有国王用0表示。
①预处理在一行之内合法的情况。也就是不能有相邻的1。
听说正解是用dfs跑的,我直接打了一个for循环。n最大只有9,状态数最多有2^9,不会超时。每种状态存在exist数组里
②预处理哪两种状态是可以挨着的,也就是上下两行可以同时存在的状态。同样记在一个数组里。上一个预处理时,可以把状态存到数组里,然后直接调用下标。存can数组
③同时,还要记录一下每一种状态的国王的数量,记为cnt数组。
④dp数组:dp[i][j][pos]表示放到第i行,已经放了j个国王,这一行的状态的下标为pos时的方案数。转移时,枚举上一行的状态,累加。即:dp[i][j][pos]=Σdp[i-1][j-cnt[pos]][k],其中,k为枚举的上一层的状态的下标
⑤注意数据范围要开long long
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll N,K,tot=1,max_exist,ans; ll dp[15][100][1030],exist[1030],can[100][100],cnt[100]; void pre_exist() { exist[1]=0; for(ll i=1;i<=max_exist;++i) { ll x=i,last=0,flg=0,num=0; while(x) { if(x&1) { if(last==1) { flg=1; break; } last=1; num++; } else last=0; x>>=1; } if(!flg) { exist[++tot]=i; cnt[tot]=num; } } //for(ll i=1;i<=tot;++i) printf("*%lld,%lld\n",i,exist[i]); } void pre_com() { for(ll i=1;i<=tot;++i) can[1][i]=can[i][1]=true; for(ll i=2;i<=tot;++i) for(ll j=i+1;j<=tot;++j) if((exist[i]&exist[j])==0&&(exist[i]&(exist[j]<<1))==0&&(exist[i]&(exist[j]>>1))==0) can[i][j]=can[j][i]=true; } void done() { for(ll i=1;i<=tot;++i) dp[1][cnt[i]][i]=1; for(ll i=2;i<=N;++i) for(ll j=0;j<=K;++j) for(ll pos=1;pos<=tot;++pos) { if(cnt[pos]>K) continue; for(ll k=1;k<=tot;++k) if(can[pos][k]&&cnt[k]+cnt[pos]<=j)//不要忘记判断放的王的数量是否超过当前枚举的j dp[i][j][pos]+=dp[i-1][j-cnt[pos]][k]; } } int main() { scanf("%lld%lld",&N,&K); max_exist=(1<<N)-1; pre_exist(); pre_com(); done(); for(ll i=1;i<=tot;++i) ans+=dp [K][i]; printf("%lld",ans); return 0; }
相关文章推荐
- 【SCOI2005】【codevs 2451】互不侵犯
- 【BZOJ1087】【codevs2451】互不侵犯,状压DP
- <单调栈/悬线法>codevs 2491 玉蟾宫 1159 最大全0子矩阵
- <线段树系列1> codevs 1080 线段树练习
- <序列DP>codevs 4748 低价购买
- <线段树系列2> codevs 1082 线段树练习2
- <洛谷P1896互不侵犯>(状态压缩DP)
- <线段树系列3> codevs 1082 线段树练习3
- BZOJ_P1087&Codevs_P2451 [SCOI2005]互不侵犯King(状态压缩DP)
- <矩阵快速幂>codevs 3332 数列
- <线段树系列4> codevs 4927 线段树练习5
- <tarjan||拓扑>codevs 2066 三角恋
- 【codevs 2451】互不侵犯king 状压dp
- <背包DP>codevs 1684 垃圾陷阱
- <倍增lca>codevs 3305 水果姐逛水果街Ⅱ
- <线段树版>codevs 3304 水果姐逛水果街Ⅰ
- <序列DP>codevs 2980 买帽子
- <错排>codevs 1697 ⑨要写信
- <DP>codevs 2189 数字三角形w
- <二分答案+spfa验证>codevs 1183 泥泞的道路