【BZOJ1087】【SCOI2005】【互不侵犯king】【状压dp】
2015-08-14 15:36
363 查看
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)Output
方案数。Sample Input
3 2Sample Output
16题解:状压dp经典题。
f[i][j][k]保存第i行(包括第i行)之前放了j个国王,当前行用二进制表示后对应十进制数为k的方案数。count[k]表示k所对应的二进制中1的个数。
状态转移方程比较显然:f[i][j][k]=sum{f[i-1][j-count[k]][p]};
其中k满足 (k&(k<<1))==0
其中p满足 (p&(p<<1))==0&&((p<<1)&k)==0&&(p&k)==0&&((p>>1)&k)==0
#include<iostream> #include<cstdio> #include<cmath> using namespace std; long long f[15][150][2000]; int n,kk,tot[2000],x; int main() { scanf("%d%d",&n,&kk); x=pow(2,n)-1; for (int i=0;i<=x;++i) { int j=i; while(j>0) { j&=(j-1); tot[i]++; } } for (int i=0;i<=x;i++) if ((i&(i<<1))==0) f[1][tot[i]][i]=1; for (int i=2;i<=n;i++) for (int j=0;j<=kk;j++) for (int k=0;k<=x;k++) if (((k&(k<<1))==0)&&(j>=tot[k])) { for (int s=0;s<=x;s++) if (((k&s)==0)&&((s&(s<<1))==0)&&((k&(s>>1))==0)&&((k&(s<<1))==0)) f[i][j][k]+=f[i-1][j-tot[k]][s]; } long long ans(0); for (int i=0;i<=x;i++) ans+=f [kk][i]; cout<<ans; }
相关文章推荐
- 用Delphi模拟键盘输入
- dataset数据导出到Excel
- 通过KVM_SET_USER_MEMORY_REGION操作虚拟机内存(Kernel 3.10.0 & qemu 2.0.0)
- 仿ios右滑界面返回功能
- 约瑟夫问题
- sublime text ctags使用心得
- Ubuntu开启root账号登陆SSH客服端的方法
- Linux进程的实际用户ID和有效用户ID
- Python字典
- ZOJ 1654 Place the Robots(放置机器人)------最大独立集
- PHP中 HTTP_HOST 和 SERVER_NAME 的区别
- java基础--网络编程
- win32中获得 文本框edit内容
- 关于软件开发,你老板不知道的7件事
- jQuery checkbox全选 和全部取消
- 打开64位 Ubuntu 的32位支持功能
- 在
- JavaScript的jQuery库中ready方法的学习教程
- mvc Area相关技术
- HDU 2665 Kth number(区间第K大)