题目大意

  在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。求用最少的步数移动到目标棋局的步数。

  总体思路很简单,Bfs即可,只是需要注意以下几点:

  • memcmp的返回值不一定是-1, 0, 1,而是<0, =0, >0的某个数。这在windows和linux上的效果不一样。
  • 注意:黑白双方交替走棋。
  • 任意一方都必须走一步。
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <queue>
  5. #include <set>
  6. #include <cassert>
  7. using namespace std;
  8.  
  9. const int MAX_N = 10;
  10. const int N = 4;
  11. const int Dir[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
  12.  
  13. struct Node
  14. {
  15. char A[MAX_N][MAX_N];
  16. int Level;
  17. char NextColor;
  18.  
  19. Node()
  20. {
  21. memset(A, 0, sizeof(A));
  22. Level = 0;
  23. }
  24.  
  25. Node operator = (const Node& a)
  26. {
  27. memcpy(A, a.A, sizeof(A));
  28. Level = a.Level;
  29. NextColor = a.NextColor;
  30. return *this;
  31. }
  32.  
  33. bool operator < (const Node& a) const
  34. {
  35. if (NextColor != a.NextColor)
  36. return NextColor == 'B';
  37. else
  38. return memcmp(A, a.A, sizeof(A)) < 0;
  39. }
  40.  
  41. bool operator == (const Node& a) const
  42. {
  43. return NextColor == a.NextColor && memcmp(A, a.A, sizeof(A)) == 0;
  44. }
  45.  
  46. void OPos1(int &oRow1, int &oCol1)
  47. {
  48. for (int row = 1; row <= N; row++)
  49. for (int col = 1; col <= N; col++)
  50. if (A[row][col] == 'O')
  51. {
  52. oRow1 = row;
  53. oCol1 = col;
  54. return;
  55. }
  56. }
  57.  
  58. void OPos2(int &oRow2, int &oCol2)
  59. {
  60. int oRow1, oCol1;
  61. OPos1(oRow1, oCol1);
  62. for (int col = oCol1 + 1; col <= N; col++)
  63. if (A[oRow1][col] == 'O')
  64. {
  65. oRow2 = oRow1;
  66. oCol2 = col;
  67. return;
  68. }
  69. for (int row = oRow1 + 1; row <= N; row++)
  70. for (int col = 1; col <= N; col++)
  71. if (A[row][col] == 'O')
  72. {
  73. oRow2 = row;
  74. oCol2 = col;
  75. return;
  76. }
  77. assert(0);
  78. }
  79.  
  80. bool CanMove1(const int dRow, const int dCol)
  81. {
  82. int oRow1, oCol1;
  83. OPos1(oRow1, oCol1);
  84. int nextRow = oRow1 + dRow, nextCol = oCol1 + dCol;
  85. return A[nextRow][nextCol] == NextColor && nextRow <= N && nextRow >= 1 && nextCol <= N && nextCol >= 1;
  86. }
  87.  
  88. Node GetMove1(int dRow, int dCol)
  89. {
  90. int oRow1, oCol1;
  91. OPos1(oRow1, oCol1);
  92. Node ans = *this;
  93. swap(ans.A[oRow1][oCol1], ans.A[oRow1 + dRow][oCol1 + dCol]);
  94. return ans;
  95. }
  96.  
  97. bool CanMove2(const int dRow, const int dCol)
  98. {
  99. int oRow2, oCol2;
  100. OPos2(oRow2, oCol2);
  101. int nextRow = oRow2 + dRow, nextCol = oCol2 + dCol;
  102. return A[nextRow][nextCol] == NextColor && nextRow <= N && nextRow >= 1 && nextCol <= N && nextCol >= 1;
  103. }
  104.  
  105. Node GetMove2(int dRow, int dCol)
  106. {
  107. int oRow2, oCol2;
  108. OPos2(oRow2, oCol2);
  109. Node ans = *this;
  110. swap(ans.A[oRow2][oCol2], ans.A[oRow2 + dRow][oCol2 + dCol]);
  111. return ans;
  112. }
  113.  
  114. bool Ok()
  115. {
  116. for (int row = 1; row <= N; row++)
  117. {
  118. char st = A[row][1];
  119. bool ok = true;
  120. for (int col = 2; col <= N; col++)
  121. if (A[row][col] != st)
  122. {
  123. ok = false;
  124. break;
  125. }
  126. if (ok)
  127. return true;
  128. }
  129. for (int col = 1; col <= N; col++)
  130. {
  131. char st = A[1][col];
  132. bool ok = true;
  133. for (int row = 2; row <= N; row++)
  134. if (A[row][col] != st)
  135. {
  136. ok = false;
  137. break;
  138. }
  139. if (ok)
  140. return true;
  141. }
  142. char st = A[1][1];
  143. bool ok = true;
  144. for (int i = 2; i <= N; i++)
  145. if (A[i][i] != st)
  146. {
  147. ok = false;
  148. break;
  149. }
  150. if (ok)
  151. return true;
  152. st = A[1][N];
  153. ok = true;
  154. for (int row = 2, col = N - 1; row <= N; row++, col--)
  155. if (A[row][col] != st)
  156. {
  157. ok = false;
  158. break;
  159. }
  160. return ok;
  161. }
  162. };
  163. Node Start;
  164.  
  165. int Bfs()
  166. {
  167. static queue<Node> q;
  168. static set<Node> cache;
  169. Node s1 = Start, s2 = Start;
  170. s1.NextColor = 'B';
  171. s2.NextColor = 'W';
  172. q.push(s1);
  173. q.push(s2);
  174. cache.insert(s1);
  175. cache.insert(s2);
  176. while (!q.empty())
  177. {
  178. Node cur = q.front();
  179. q.pop();
  180. if (!(cur == s1 || cur == s2) && cur.Ok())
  181. return cur.Level;
  182. for (int i = 0; i < 4; i++)
  183. {
  184. if (cur.CanMove1(Dir[i][0], Dir[i][1]))
  185. {
  186. Node next = cur.GetMove1(Dir[i][0], Dir[i][1]);
  187. next.NextColor = (cur.NextColor == 'B' ? 'W' : 'B');
  188. if (!cache.count(next))
  189. {
  190. next.Level = cur.Level + 1;
  191. cache.insert(next);
  192. q.push(next);
  193. }
  194. }
  195. if (cur.CanMove2(Dir[i][0], Dir[i][1]))
  196. {
  197. Node next = cur.GetMove2(Dir[i][0], Dir[i][1]);
  198. next.NextColor = (cur.NextColor == 'B' ? 'W' : 'B');
  199. if (!cache.count(next))
  200. {
  201. next.Level = cur.Level + 1;
  202. cache.insert(next);
  203. q.push(next);
  204. }
  205. }
  206. }
  207. }
  208. return -1;
  209. }
  210.  
  211. int main()
  212. {
  213. for (int i = 1; i <= 4; i++)
  214. scanf("%s", Start.A[i] + 1);
  215. printf("%d\n", Bfs());
  216. return 0;
  217. }

  

luogu2346 四子连棋的更多相关文章

  1. codevs1004四子连棋[BFS 哈希]

    1004 四子连棋   时间限制: 1 s   空间限制: 128000 KB   题目等级 : 黄金 Gold   题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗 ...

  2. Codevs p1004 四子连棋

                          四子连棋 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向 ...

  3. 【宽度优先搜索】神奇的状态压缩 CodeVs1004四子连棋

    一.写在前面 其实这是一道大水题,而且还出在了数据最水的OJ上,所以实际上这题并没有什么难度.博主写这篇blog主要是想写下一个想法--状态压缩.状态压缩在记录.修改状态以及判重去重等方面有着极高的( ...

  4. codevs 1004 四子连棋

    1004 四子连棋  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白 ...

  5. codevs 1004 四子连棋 BFS、hash判重

    004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold       题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋 ...

  6. 【洛谷 P2346】四子连棋(状态压缩,搜索)

    其实这题可以直接二进制状压做,1表示黑棋,0表示白棋,另外记录下2个空点的位置就行了. 具体看代码(冗长): #include <iostream> #include <cstdio ...

  7. 迭代加深搜索[codevs1004 四子连棋]

    迭代加深搜索 一.算法简介 迭代加深搜索是在速度上接近广度优先搜索,空间上和深度优先搜索相当的搜索方式.由于在使用过程中引入了深度优先搜索,所以也可以当作深度优先搜索的优化方案. 迭代加深搜索适用于当 ...

  8. codevs1004四子连棋

    1004 四子连棋  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白 ...

  9. P2346 四子连棋

    P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...

随机推荐

  1. 十年后我不会log,还是活的很好啊

    混迹于互联网也一两年了,出于喜爱与生活压力依然会从事很久.迟迟不写博客,大概是觉得知识与经验积累在笔记上时不时看看就好了,而实际情况是笔记很少翻,遇到问题搜博客和百度依然是首选,故开通博客记录自己工作 ...

  2. java基础学习之内存分析(栈、堆、方法区)

    栈存放:会为每个方法(包括构造函数)开辟一个栈指针,方法执行完毕后,会自动退出,并释放空间,主要每个方法中的存放局部变量 局部变量   先进后出 自下而上存储 方法执行完毕 自动释放空间 堆: 存放n ...

  3. IDEA中springboot项目打包成jar

      springboot的打包方式有很多种.有打成war的,有打成jar的,也有直接提交到github,通过jekins进行打包部署的.这里主要介绍如何打成jar进行部署.不推荐用war,因为spri ...

  4. Could not resolve type alias 'map '. Cause: java.lang.ClassNotFoundException: Cannot find class: map

    把resultType改为resultMap, 把parameterType改为parameterMap,重新发布并运行.

  5. Don't make me think [读书笔记] [思维导图]

      <Don't make me think>第3版 内容:解析用户心理,在用户模式.扫描设计.导航设计.主页布局.可用性测试,提出了许多的独到观点及建议. 特色:语言轻松.实在.配有许多 ...

  6. 微信小程序,获取点击元素的索引值index

    1.需求说明 点击 “加号图片” 上传图片,需要知道点击的是第几个图片,动态的修改src数组,这里图片用的 wx:for 循环出来的 2.遇到问题 按照官方最新文档循环的方式,索引值是以  wx:fo ...

  7. CCF201609-2 火车购票 java(100分)

    试题编号: 201609-2 试题名称: 火车购票 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配. 假设一 ...

  8. fillder抓取APP数据之小程序

    1.下载fillder ,fillder官网:https://www.telerik.com/fiddler 2.安装好后设置fillder: 工具—>选项,打开设置面板.选择HTTPS选项卡. ...

  9. 部署live555到云

    1.下载live555源码:    wget http://www.live555.com/liveMedia/public/live.2017.10.28.tar.gz    2.解压源码包:   ...

  10. Quadtrees(四分树)

    uva 297 Quadtrees Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Subm ...