[C] 2013腾讯马拉松初赛 ACM 郑厂长系列故事——N骑士问题 →→→→→进入此内容的聊天室

来自 , 2021-01-20, 写在 C, 查看 105 次.
URL http://www.code666.cn/view/8cbd005a
  1. /*
  2.  
  3. 2013腾讯马拉松初赛第5场
  4.  
  5. 1005 郑厂长系列故事——N骑士问题
  6.  
  7. Time Limit: 3.0 Seconds   Memory Limit: 65536K
  8.  
  9.  
  10. 郑厂长不是正厂长
  11. 也不是副厂长
  12. 他根本就不是厂长
  13. 还是那个腾讯公司的码农
  14. 一个业余时间喜欢下棋的码农
  15.  
  16. 最近,郑厂长对八皇后问题很感兴趣,拿着国际象棋研究了好几天,终于研究透了。兴奋之余,坐在棋盘前的他又开始无聊了。无意间,他看见眼前的棋盘上只摆了八个皇后,感觉空荡荡的,恰好又发现身边还有几个骑士,于是,他想把这些骑士也摆到棋盘上去,当然棋盘上的一个位置只能放一个棋子。因为受八皇后问题的影响,他希望自己把这些骑士摆上去之后,也要满足每2个骑士之间不能相互攻击。
  17. 现在郑厂长想知道共有多少种摆法,你能帮助他吗?
  18.  
  19. 骑士的下法:
  20. 每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走“日”字)。可以越子,没有"中国象棋"的"蹩马腿"限制。
  21.  
  22. Input
  23.  
  24. 输入第一行为一个整数T(1<=T<=8),表示有T组测试数据;
  25. 每组数据首先是一个整数N(1<=n<=10),表示要摆N个骑士上去;
  26. 接下来是一个8*8的矩阵来描述一个棋盘,’.’表示这个位置是空的,’*’表示这个位置上已经放了皇后了;
  27. 数据中的初始棋盘保证是一个合法的八皇后摆法。
  28.  
  29. Output
  30.  
  31. 对每组数据,请在一行内输出一个整数,表示合法的方案数。
  32.  
  33. Sample Input
  34.  
  35. 2
  36. 1
  37. *.......
  38. ....*...
  39. .......*
  40. .....*..
  41. ..*.....
  42. ......*.
  43. .*......
  44. ...*....
  45. 2
  46. *.......
  47. ....*...
  48. .......*
  49. .....*..
  50. ..*.....
  51. ......*.
  52. .*......
  53. ...*....
  54.  
  55.  
  56. Sample Output
  57.  
  58. 56
  59. 1409
  60.  
  61.  
  62.  
  63.  
  64. */
  65.  
  66. /*
  67. 解题报告:
  68.  
  69. 一看这数据范围就想到了状态压缩DP,由于马的攻击范围最多是上下2行。
  70. 所以我们只要管好前面两行的就行了,
  71. dp[i][j][p][q]
  72. 表示第i行放马的状态是q,第i-1行的状态是p,前i行放马的个数是j个的种数。
  73.  
  74. 推i+1行的时候枚举第i+1行放马的状态,进行转移。
  75.  
  76. 总的复杂度无法估计,理论上是(1<<8)*(1<<8)*(1<<8)*n*8
  77. 这里需要一些剪枝,不然是通不过的。加了很多的非法判断。
  78. */
  79.  
  80.  
  81. #include<cstdio>
  82. #include<cstring>
  83. #include<algorithm>
  84. #include<cmath>
  85. #include<iostream>
  86. #include<map>
  87. #include<string>
  88. #include<queue>
  89. #include<stack>
  90. #include<vector>
  91. #include<set>
  92. #include<list>
  93. using namespace std;
  94. typedef __int64 lld;
  95. const int MAX = 10;
  96. const int INF = 1000000000;
  97. const double EPS = 1.0e-8;
  98. const int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}};
  99. int dblcmp(double x) {
  100.     if(fabs(x) < EPS)return 0;
  101.     return x < 0 ? -1 : 1;
  102. }
  103. int a[MAX];
  104. lld dp[2][11][1 << 8][1 << 8];
  105. char s[MAX];
  106. bool ok1[1 << 8][1 << 8];
  107. bool ok2[1 << 8][1 << 8];
  108. bool judge(int a, int b, int d) {
  109.     int i;
  110.     int x, y;
  111.     for(i = 0; i + d - 1 < 8; i++) {
  112.         x = 1 << i;
  113.         y = 1 << i << d;
  114.         if((x & a) && (y & b))return false;
  115.         if((x & b) && (y & a))return false;
  116.     }
  117.     return true;
  118. }
  119. int cnt[1 << 8];
  120. int count(int n) {
  121.     int ret = 0;
  122.     while(n) {
  123.         ret += n & 1;
  124.         n >>= 1;
  125.     }
  126.     return ret;
  127. }
  128. int main() {
  129.  
  130.     int n = 6;
  131.     int i, j;
  132.     int k;
  133.     int T;
  134.     int CS = 1;
  135.     for(i = 0; i < (1 << 8); i++) {
  136.         for(j = 0; j < (1 << 8); j++) {
  137.             ok1[i][j] = judge(i, j, 1);
  138.             ok2[i][j] = judge(i, j, 2);
  139.         }
  140.     }
  141.     for(i = 0; i < (1 << 8); i++) {
  142.         cnt[i] = count(i);
  143.         //    printf("cnt[%d]=%d\n",i,cnt[i]);
  144.     }
  145.     //printf("%d\n",1<<8);
  146.     scanf("%d", &T);
  147.     while(T--) {
  148.         scanf("%d", &n);
  149.         for(i = 0; i < 8; i++) {
  150.             scanf("%s", s);
  151.             a[i] = 0;
  152.             for(j = 0; j < 8; j++) {
  153.                 a[i] *= 2;
  154.                 if(s[j] == '*')a[i]++;
  155.             }
  156.             //    printf("a[%d]=%d\n",i,a[i]);
  157.         }
  158.  
  159.         memset(dp, 0, sizeof(dp));
  160.         int xx = 0;
  161.         for(i = 0; i < (1 << 8); i++) {
  162.             if(i & a[0])continue;
  163.             if(cnt[i] > n)continue;
  164.             dp[0][cnt[i]][0][i]++;
  165.             xx++;
  166.             //printf("i=%d\n",i);
  167.         }
  168.         //    printf("xx=%d\n",xx);
  169.         int tag = 0;
  170.         for(i = 1; i < 8; i++) {
  171.             tag = i & 1;
  172.             for(xx = 0; xx <= n; xx++) {
  173.                 for(j = 0; j < (1 << 8); j++) {
  174.                     for(k = 0; k < (1 << 8); k++) {
  175.                         dp[tag][xx][j][k] = 0;
  176.                     }
  177.                 }
  178.             }
  179.             for(j = 0; j < (1 << 8); j++) {
  180.                 if(i - 2 >= 0 && (j & a[i - 2]))continue;
  181.  
  182.                 for(k = 0; k < (1 << 8); k++) {
  183.                     if(k & a[i - 1])continue;
  184.  
  185.                     if(cnt[j] + cnt[k] > n)continue;
  186.                     if(!ok2[j][k])continue;
  187.                     int tt;
  188.  
  189.                     for(tt = cnt[j] + cnt[k]; tt <= n; tt++) {
  190.                         if(dp[1 - tag][tt][j][k] == 0)continue;
  191.  
  192.                         for(int z = 0; z < (1 << 8); z++) {
  193.                             if(cnt[z] + tt > n)continue;
  194.                             if(z & a[i])continue;
  195.                             if(!ok2[z][k] || !ok1[z][j])continue;
  196.                             dp[tag][tt + cnt[z]][k][z] += dp[1 - tag][tt][j][k];
  197.                         }
  198.                     }
  199.                 }
  200.             }
  201.  
  202.         }
  203.  
  204.         lld ans = 0;
  205.         for(i = 0; i < (1 << 8); i++) {
  206.             for(j = 0; j < (1 << 8); j++) {
  207.                 //if(dp[tag][n][i][j]>0)printf("%d %d\n",i,j);
  208.                 ans += dp[tag][n][i][j];
  209.             }
  210.         }
  211.         printf("%I64d\n", ans);
  212.     }
  213.     return 0;
  214. }
  215. /*
  216. 2
  217. 1
  218. *.......
  219. ....*...
  220. .......*
  221. .....*..
  222. ..*.....
  223. ......*.
  224. .*......
  225. ...*....
  226.  
  227.  
  228. 2
  229. 1
  230. ........
  231. ........
  232. ........
  233. ........
  234. ........
  235. ........
  236. ........
  237. ........
  238.  
  239. 2
  240. 1
  241. *******.
  242. ********
  243. ********
  244. ********
  245. ********
  246. ********
  247. ********
  248. ********
  249. */
  250.  

回复 "2013腾讯马拉松初赛 ACM 郑厂长系列故事——N骑士问题"

这儿你可以回复上面这条便签

captcha