N骑士问题 HDU4529
2015-08-04 10:37
381 查看
最近,郑厂长对八皇后问题很感兴趣,拿着国际象棋研究了好几天,终于研究透了。兴奋之余,坐在棋盘前的他又开始无聊了。无意间,他看见眼前的棋盘上只摆了八个皇后,感觉空荡荡的,恰好又发现身边还有几个骑士,于是,他想把这些骑士也摆到棋盘上去,当然棋盘上的一个位置只能放一个棋子。因为受八皇后问题的影响,他希望自己把这些骑士摆上去之后,也要满足每2个骑士之间不能相互攻击。
现在郑厂长想知道共有多少种摆法,你能帮助他吗?
骑士的下法:
每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走“日”字)。可以越子,没有”中国象棋”的”蹩马腿”限制。
一道简单的状态压缩dp,和皇后并没有什么关系,只是摆了皇后的地方不能摆骑士。
dp[i][num][j][k] 记录四个状态:
i 代表第 i 行
num 代表前i-1行里共有num个骑士
j 代表 i-1行的状态
k 代表 i 行的状态
转移方程 dp[i][cnt+num][k][l] += dp[i-1][num][j][k];
cnt 为当前行的骑士个数 l 代表第 i 行 ,k 代表 i - 1行,j代表 i - 2 行
直接暴力写肯定会跪,刚写出来本地运行一个用例要2秒多,加上一些简单的优化就搞定了。
现在郑厂长想知道共有多少种摆法,你能帮助他吗?
骑士的下法:
每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走“日”字)。可以越子,没有”中国象棋”的”蹩马腿”限制。
一道简单的状态压缩dp,和皇后并没有什么关系,只是摆了皇后的地方不能摆骑士。
dp[i][num][j][k] 记录四个状态:
i 代表第 i 行
num 代表前i-1行里共有num个骑士
j 代表 i-1行的状态
k 代表 i 行的状态
转移方程 dp[i][cnt+num][k][l] += dp[i-1][num][j][k];
cnt 为当前行的骑士个数 l 代表第 i 行 ,k 代表 i - 1行,j代表 i - 2 行
直接暴力写肯定会跪,刚写出来本地运行一个用例要2秒多,加上一些简单的优化就搞定了。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int N; int G[10]; int dp[10][11][1<<8][1<<8]; //行数(从第二行开始) 前i行骑士个数 //i-2行状态 i-1行状态 int lowbit(int k) { return k&(-k); } int cal(int n) { int res = 0; while(n) { res++; n -= lowbit(n); } return res; } int main() { int T; scanf("%d",&T); while(T--) { memset(G,0,sizeof(G)); memset(dp,0,sizeof(dp)); scanf("%d",&N); for(int i=2;i<=9;i++) { getchar(); for(int j=0;j<8;j++) { char c; scanf("%c",&c); if(c == '*') G[i] |= 1 << j; } } dp[1][0][0][0] = 1; int res = 0; int tot = 1 << 8; for(int i=2;i<=9;i++) for(int j=0;j<tot;j++) {// 前两行 if(G[i-2] & j) continue; for(int k=0;k<tot;k++) {//前一行 if(G[i-1] & k) continue; for(int l=0;l<tot;l++) { if(G[i] & l) continue; int jj = 0; //前两行对本行的影响 jj |= j << 1; jj |= j >> 1; jj &= tot - 1; int kk = 0; //前一行对本行的影响 kk |= k << 2; kk |= k >> 2; kk &= tot - 1; if((jj|kk) & l) continue; int cnt = cal(l); for(int num=0;num+cnt<=N;num++) { dp[i][cnt+num][k][l] += dp[i-1][num][j][k]; if(i == 9 && cnt + num == N) res += dp[i-1][num][j][k]; } } } } printf("%d\n",res); } return 0; }
相关文章推荐
- HDU 1166 敌兵布阵 (树状数组)
- 找回Home文件夹(library父文件夹)
- C语言基础100例
- Https(SSL/TLS)原理详解
- C/C++ VS2013 动态链接库详解
- getResource().getPath() 路径带问题展开
- 修改Android中strings.xml文件, 动态改变数据
- Linux下python升级步骤
- 求最短路的相关方法
- 南邮 OJ 1080 悄悄话游戏
- POJ2184--Cow Exhibition
- HDU 1241:Oil Deposits【递归】
- TIBCO JMS Message Selectors: How to Filter EMS Messages in TIBCO
- 南邮 OJ 1079 111…
- poj解题报告——1067
- 拓扑排序进阶
- Android之Activity的几种跳转方式
- 如何用Redis做LRU-Cache
- BluetoothAdapter.LeScanCallback 参考文档
- iOS多线程之NSOperation,NSOperationQueue