[NOIP 2011] Mayan游戏:搜索,模拟
来源:互联网 发布:web服务器 并发 java 编辑:程序博客网 时间:2024/06/07 02:32
题意:寻找一个用n步(0<n<=5)完成5*7的Mayan游戏的字典序最小的方案。
每个方块可以左移、右移,至多5步,共有少于5.6亿个可能的情形。3秒内搜一搜是可行的。
怎样消除方块呢?由于要求一次性消完所有能消的方块,而且横、竖有公共部分则全部消掉,所以不能找到就消。找到连续三个就标记,每次循环根据标记进行清除,循环到不能再消。
怎样使方块下落呢?从下往上模拟,让方块掉到不能再掉的地方,而不是只掉一格。
BZOJ上NOIP十连测里做了一道模拟,虽然游戏不同,但是对下落的模拟是类似的。
朴素的搜索(暴力)TLE两组。什么地方可以剪枝呢?最优性?可行性?似乎都不行。有没有做重复的工作呢?有。如果有相邻的两个方块,把左边的往右移和把右边的往左移是等价的,由于要求字典序最小,考虑前者即可。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int X = 5, Y = 7, N = 5, sz = X*Y*sizeof(int);int n, M[X][Y];struct op { int x, y, g;} S[N];inline bool empty(){ for (int i = 0; i < X; ++i) for (int j = 0; j < Y; ++j) if (M[i][j]) return false; return true;}void fall(){ for (int i = 0; i < X; ++i) for (int j = 1; j < Y; ++j) { if (!M[i][j]) continue; for (int k = j-1; k >= 0 && !M[i][k]; --k) swap(M[i][k], M[i][k+1]); }}void clear(){ static bool b[X][Y]; memset(b, 0, sizeof(b)); bool ok = false; do { fall(); ok = true; for (int i = 1; i < X-1; ++i) for (int j = 0; j < Y; ++j) if (M[i][j] && M[i-1][j] == M[i][j] && M[i][j] == M[i+1][j]) b[i-1][j] = b[i][j] = b[i+1][j] = true; for (int i = 0; i < X; ++i) for (int j = 1; j < Y-1; ++j) if (M[i][j] && M[i][j-1] == M[i][j] && M[i][j] == M[i][j+1]) b[i][j-1] = b[i][j] = b[i][j+1] = true; for (int i = 0; i < X; ++i) for (int j = 0; j < Y; ++j) if (b[i][j]) { ok = false; b[i][j] = false; M[i][j] = 0; } } while (!ok);}bool dfs(int);inline bool move(int d, int i, int j, int g, int T[X][Y]){ S[d] = (op){i, j, g}; swap(M[i][j], M[i+g][j]); clear(); bool ret = dfs(d+1); memcpy(M, T, sz); return ret;}bool dfs(int d){ if (d == n) return empty(); int T[X][Y]; memcpy(T, M, sz); for (int i = 0; i < X; ++i) for (int j = 0; j < Y; ++j) { if (!M[i][j]) continue; if (i < X-1 && move(d, i, j, 1, T) || i && !M[i-1][j] && move(d, i, j, -1, T)) return true; } return false;}int main(){ scanf("%d", &n); for (int i = 0; i < X; ++i) for (int j = 0, c; scanf("%d", &c), c; ++j) M[i][j] = c; if (!dfs(0)) puts("-1"); else for (int i = 0; i < n; ++i) printf("%d %d %d\n", S[i].x, S[i].y, S[i].g); return 0;}
0 0
- [NOIP 2011] Mayan游戏:搜索,模拟
- 【noip】Mayan游戏 搜索
- [NOIP 2011] Mayan游戏
- NOIP 2011 Mayan游戏
- NOIP 2011 Mayan游戏
- NOIP 2011 Mayan游戏
- Mayan 游戏(2011NOIP)
- 【NOIP 2011】mayan游戏 - Pascal
- NOIP 2011 Day1T3 Mayan游戏
- NOIP提高组2011 Mayan游戏
- noip提高组2011 mayan游戏
- [NOIP2011]Mayan游戏【搜索】
- NOIP2011 Mayan游戏(搜索)
- 【NOIP2011】Mayan游戏 搜索
- 【搜索】[NOIP2012]mayan游戏
- NOIP 2011 题解 铺地毯 选择客栈 Mayan 游戏
- 「2011NOIP提高组」Mayan 游戏(Mayan Puzzle)
- noip2011 Mayan游戏 dfs+模拟
- [LeetCode]149. Max Points on a Line
- 如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器
- solution of POJ: 1328.Radar Installation
- 395.Coins in a Line II-硬币排成线 II(中等题)
- vim 使用
- [NOIP 2011] Mayan游戏:搜索,模拟
- HDOJ1002A + B Problem II
- 富人送了穷人一头牛,结果牛死了,看懂的离成功不远了!
- Java面试手写代码No.1(JDBC)
- 齐博cms老漏洞分析
- BeanUtil组件
- Storm 性能优化
- 对极几何--基本矩阵F
- linux 的密码问题 ---不带显示的