题目大意

Mayan puzzle是最近流行起来的一个游戏。游戏界面是一个77 行\times 5×5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:

1 、每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参见输入输出样例说明中的图66到图77 );如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图1 和图2);

2 、任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除(参见图1 到图3)。

注意:

a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如下面图44 ,三个颜色为11 的方块和三个颜色为 22 的方块会同时被消除,最后剩下一个颜色为22的方块)。

b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除(例如下面图5 所示的情形,5 个方块会同时被消除)。

3 、方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除。

上面图1 到图 3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐标为(0, 0 ),将位于(3, 3 )的方块向左移动之后,游戏界面从图 1 变成图 2 所示的状态,此时在一竖列上有连续三块颜色为4 的方块,满足消除条件,消除连续3 块颜色为4 的方块后,上方的颜色为3 的方块掉落,形成图 3 所示的局面。

若有解,输出具体移动方案,否则输出-1.

题解

如何模拟消除过程

  1. 每当我们消除掉一组块后,剩余的块新的排列方式我们是不可预估的。所以,我们应当不断对全局进行可消除的块的搜索并消除,而不是删除哪个块就在哪个块附近尝试考虑各种情况来删除。
  2. 对于一组块如何删除?一定不要忘记图5的情况!另外,在时间复杂度够的情况下,我们要尽可能使用简单粗暴的形式解决问题。与其边删块边让上面的块下落,不如删的时候只删不下落,最后设置个DropAll函数把所有块整体下落,这样一定不会错。

如何剪枝

  1. 优化搜索顺序:根据题目中的优先级,我们可以按从左到右、从下至上进行搜索。
  2. 排除等效冗余:我们不允许两个颜色相同的块交换;所有块不可以与左侧相邻的块交换。
  3. 可行性剪枝:本题看不出什么规律来,无法在此处剪枝。
  4. 最优性剪枝:本题没要你求最优解,无法在此处剪枝。
  5. 记忆化:本题状态存储不了,无法在此处剪枝。
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <cassert>
  5. using namespace std;
  6.  
  7. const int MAX_ROW = 10, MAX_COL = 10;
  8. const int TotX = 5, TotY = 7;
  9. int N;
  10.  
  11. struct Matrix
  12. {
  13. int A[MAX_ROW][MAX_COL];
  14.  
  15. private:
  16. int GetHorSum(int x, int y)
  17. {
  18. int color = A[x][y];
  19. int ans = 1;
  20. for (int i = x - 1; i >= 0 && A[i][y] == color; i--)
  21. ans++;
  22. for (int i = x + 1; i < TotX && A[i][y] == color; i++)
  23. ans++;
  24. return ans;
  25. }
  26.  
  27. int GetVerSum(int x, int y)
  28. {
  29. int color = A[x][y];
  30. int ans = 1;
  31. for (int i = y + 1; i < TotY && A[x][i] == color; i++)
  32. ans++;
  33. for (int i = y - 1; i >= 0 && A[x][i] == color; i--)
  34. ans++;
  35. return ans;
  36. }
  37.  
  38. void DropOne(int x, int y)
  39. {
  40. if (A[x][y])
  41. for (int i = y - 1; i >= 0 && !A[x][i]; i--)
  42. swap(A[x][i], A[x][i + 1]);
  43. }
  44.  
  45. void DropAll()
  46. {
  47. for (int x = 0; x < TotX; x++)
  48. for (int y = 0; y < TotY; y++)
  49. DropOne(x, y);
  50. }
  51.  
  52. void RemoveHor(int, int);
  53. void RemoveVer(int, int);
  54.  
  55. bool Remove(int x, int y)
  56. {
  57. if (GetHorSum(x, y) >= 3)
  58. {
  59. RemoveHor(x, y);
  60. DropAll();
  61. return true;
  62. }
  63. if (GetVerSum(x, y) >= 3)
  64. {
  65. RemoveVer(x, y);
  66. DropAll();
  67. return true;
  68. }
  69. return false;
  70. }
  71.  
  72. bool Search_Remove()
  73. {
  74. for (int x = 0; x < TotX; x++)
  75. for (int y = 0; y < TotY && A[x][y]; y++)
  76. if (Remove(x, y))
  77. return true;
  78. return false;
  79. }
  80.  
  81. void RemoveAll()
  82. {
  83. while (Search_Remove());
  84. }
  85.  
  86. public:
  87. Matrix operator = (const Matrix& a)
  88. {
  89. memcpy(A, a.A, sizeof(a.A));
  90. return *this;
  91. }
  92.  
  93. bool operator == (const Matrix& a) const
  94. {
  95. return !memcmp(A, a.A, sizeof(A));
  96. }
  97.  
  98. bool Empty()
  99. {
  100. for (int x = 0; x < TotX; x++)
  101. if (A[x][0])
  102. return false;
  103. return true;
  104. }
  105.  
  106. Matrix Move(int x, int y, int dir)
  107. {
  108. Matrix ans;
  109. ans = *this;
  110. assert(ans.A[x][y]);
  111. assert(x + dir < TotX && x + dir >= 0);
  112. if (ans.A[x + dir][y])
  113. swap(ans.A[x][y], ans.A[x + dir][y]);
  114. else
  115. {
  116. swap(ans.A[x][y], ans.A[x + dir][y]);
  117. ans.DropAll();
  118. }
  119. ans.RemoveAll();
  120. return ans;
  121. }
  122. };
  123.  
  124. void Matrix::RemoveHor(int x, int y)
  125. {
  126. int color = A[x][y];
  127. A[x][y] = 0;
  128. for (int i = x - 1; i >= 0 && A[i][y] == color; i--)
  129. {
  130. if (GetVerSum(i, y) >= 3)
  131. RemoveVer(i, y);
  132. A[i][y] = 0;
  133. }
  134. for (int i = x + 1; i < TotX && A[i][y] == color; i++)
  135. {
  136. if (GetVerSum(i, y) >= 3)
  137. RemoveVer(i, y);
  138. A[i][y] = 0;
  139. }
  140. }
  141.  
  142. void Matrix::RemoveVer(int x, int y)
  143. {
  144. int color = A[x][y];
  145. A[x][y] = 0;
  146. for (int i = y - 1; y >= 0 && A[x][i] == color; i--)
  147. {
  148. if (GetHorSum(x, i) >= 3)
  149. RemoveHor(x, i);
  150. A[x][i] = 0;
  151. }
  152. for (int i = y + 1; y < TotY && A[x][i] == color; i++)
  153. {
  154. if (GetHorSum(x, i) >= 3)
  155. RemoveHor(x, i);
  156. A[x][i] = 0;
  157. }
  158. }
  159.  
  160. struct State
  161. {
  162. Matrix mat;
  163. int X, Y, Dir;
  164. }States[10];
  165.  
  166. bool Ok(int cnt)
  167. {
  168. for (int i = 0; i < cnt; i++)
  169. if (States[i].mat == States[cnt].mat)
  170. return false;
  171. return true;
  172. }
  173.  
  174. int Dfs(int cnt)
  175. {
  176. if (cnt > N)
  177. return -1;
  178. for (int x = 0; x < TotX; x++)
  179. for (int y = 0; y < TotY && States[cnt - 1].mat.A[x][y]; y++)
  180. {
  181. States[cnt].X = x;
  182. States[cnt].Y = y;
  183. const Matrix& matFrom = States[cnt - 1].mat;
  184. if (x <= TotX - 2 && matFrom.A[x + 1][y] != matFrom.A[x][y])
  185. {
  186. States[cnt].Dir = 1;
  187. States[cnt].mat = States[cnt - 1].mat.Move(x, y, 1);
  188. if (States[cnt].mat.Empty())
  189. return cnt;
  190. if (Ok(cnt))
  191. {
  192. int nextAns = Dfs(cnt + 1);
  193. if (nextAns > -1)
  194. return nextAns;
  195. }
  196. }
  197. if (x >= 1 && !matFrom.A[x - 1][y])
  198. {
  199. States[cnt].Dir = -1;
  200. States[cnt].mat = States[cnt - 1].mat.Move(x, y, -1);
  201. if (States[cnt].mat.Empty())
  202. return cnt;
  203. if (Ok(cnt))
  204. {
  205. int nextAns = Dfs(cnt + 1);
  206. if (nextAns > -1)
  207. return nextAns;
  208. }
  209. }
  210. }
  211. return -1;
  212. }
  213.  
  214. int main()
  215. {
  216. scanf("%d", &N);
  217. for (int x = 0; x < TotX; x++)
  218. for (int y = 0; scanf("%d", &States[0].mat.A[x][y]) && States[0].mat.A[x][y]; y++);
  219.  
  220. int cnt = Dfs(1);
  221. if (cnt == -1)
  222. printf("-1\n");
  223. else
  224. {
  225. for (int i = 1; i <= cnt; i++)
  226. printf("%d %d %d\n", States[i].X, States[i].Y, States[i].Dir);
  227. }
  228. return 0;
  229. }

  

luogu1312 Mayan游戏 剪枝的更多相关文章

  1. [noip2011 luogu1312] Mayan游戏(模拟)

    原题:传送门 大模拟- 两个剪枝: 1.如果左边不为空就不往左边走(因为一定不如左边的移到右边优) 2.如果相邻两颜色相同不需移动 当然也有别的小剪枝(我没写)比如如果当前某一颜色剩余块数满足1< ...

  2. NOIP2011 Mayan游戏

    3 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上 ...

  3. noip提高组2011 Mayan游戏

    Mayan游戏 描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.**游戏通关 ...

  4. $Mayan$游戏

    \(Mayan\)游戏 好啊,一年(半年)来的梦魇,终于结束了. 其实我从来没料到整体竟然会如此暴力--做的时候机房里冷得很,感觉晕晕乎乎地做完了,晕晕乎乎地调了好久,晕晕乎乎地听(看了题解的)\(q ...

  5. [Luogu 1312] noip11 Mayan游戏

    [Luogu 1312] noip11 Mayan游戏 Problem: Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即 ...

  6. Luogu P1312 Mayan游戏(搜索)

    P1312 Mayan游戏 题意 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个\(7\)行\(\times 5\)列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必 ...

  7. 洛谷P1312 [NOIP2011提高组Day1T3]Mayan游戏

    Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游 ...

  8. [题目] Luogu P1312 Mayan游戏

    题面 题目描述 $ Mayan puzzle $是最近流行起来的一个游戏.游戏界面是一个 \(7行 \times 5列\)的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放 ...

  9. 洛谷P1312 Mayan游戏

    P1312 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他 ...

随机推荐

  1. 【1】Jdk1.8中的HashMap实现原理

    HashMap概述 HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. 内部实现 ...

  2. Android 解决ScrollView嵌套RecyclerView导致滑动不流畅的问题

    最近做的项目中遇到了ScrollView嵌套RecyclerView,刚写完功能测试,直接卡出翔了,后来通过网上查找资料和 自己的实践,找出了两种方法解决这个问题. 首先来个最简单的方法: recyc ...

  3. sql中表变量

    今天在公司看sql优化的文章的时候,提到了表变量,做下笔记. 表变量 顺便复习下临时表.

  4. 查看/进入mac根目录的方式

    1.通过“前往文件夹”快捷键组合 (1)打开finder,点击上部菜单栏“前往”,然后“个人”,直接跳转. (2)快捷键组合:command + shift + G:注意:打开finder后,再快捷键 ...

  5. CSS——dispaly、overflow、visibility、opacity

    隐藏盒子: 1.overflow:hidden;             隐藏盒子超出的部分. 2.display: none;                    隐藏盒子,而且不占位置.(用的最 ...

  6. html——表单控件

    基本的表单控件还有html5的一些新的表单控件: <!DOCTYPE html> <html> <head> <meta charset="utf- ...

  7. 在CentOS下搭建Android 开发环境

    在CentOS下搭建Android 开发环境 目录 1.环境搭建 1.1.JDK安装 1.2.Eclipse安装 1.3.ADT安装 1.4.Android SDK安装 1.5.Android NDK ...

  8. windows编译MaskRCNN

    1.代码修改为3.0语言版本 2.setup_windows.py 文件内容为 #!/usr/bin/env python import numpy as np import os # on Wind ...

  9. Linux Shell ssh登录脚本

    Linux 登陆服务器敲命令太多,某时候确实不便,所以就用shell写了一个  我的blog地址: http://www.cnblogs.com/caoguo 一.说明 支持秘密和密钥两种格式 用户名 ...

  10. Sping——使用注解创建切面

    为讲解例子,我们首先定义一个Performance接口: package aoptest; public interface Performance { public void perform(); ...