P1312 Mayan遊戲 題解
阿新 • • 發佈:2020-07-29
思路很簡單, 模擬, 搜尋
注意向左交換和向右交換其實是等價的, 所以不用列舉向左交換(因為優先向右交換)
但是如果當前列舉的塊左邊為空, 不存在過從左邊向右交換的情況, 所以這種情況要額外判斷, 多一個向左交換的搜尋子樹
程式碼
#include <cstdio> #include <cstring> int n; struct M { int a[8][6]; inline bool down(int x, int y) { int b[8]; for (register int i = 1; i <= 7; i++) b[i] = a[i][y]; for (register int i = x; i >= 1; i--) if (b[i]) { for (register int j = i; j >= 1; j--) a[x + (j - i)][y] = b[j], a[j][y] = 0; return 1; } return 0; } inline bool fall() { bool flag = 0; for (register int i = 1; i <= 5; i++) for (register int j = 7; j >= 2; j--) if (!a[j][i] && !(flag |= down(j, i))) break; return flag; } inline void del() { int b[8][6]; memcpy(b, a, sizeof(a)); for (register int i = 1; i <= 7; i++) for (register int j = 1; j <= 5; j++) if (a[i][j]) { if(j >= 2 && j <= 4 && a[i][j - 1] == a[i][j] && a[i][j + 1] == a[i][j]) b[i][j] = b[i][j - 1] = b[i][j + 1] = 0; if(i >= 1 && i <= 6 && a[i - 1][j] == a[i][j] && a[i + 1][j] == a[i][j]) b[i][j] = b[i - 1][j] = b[i + 1][j] = 0; } memcpy(a, b, sizeof(b)); } inline bool empty() { for (register int i = 1; i <= 7; i++) for (register int j = 1; j <= 5; j++) if (a[i][j]) return 0; return 1; } inline void update() { do del(); while(fall()); } M drag(int x, int y, int g) { M nxt = *this; nxt[x][y] ^= nxt[x][y + g]; nxt[x][y + g] ^= nxt[x][y]; nxt[x][y] ^= nxt[x][y + g]; nxt.update(); return nxt; } void print() { puts("---------"); for (int i = 1; i <= 7; i++) { for (int j = 1; j <= 5; j++) printf("%d ", a[i][j]); puts(""); } puts("---------"); } bool operator==(M b) { for (register int i = 1; i <= 7; i++) for (register int j = 1; j <= 5; j++) if (a[i][j] != b[i][j]) return 0; return 1; } int* operator[](int i) { return a[i]; } M () { memset(a, 0, sizeof(a)); } M (int v) { memset(a, v, sizeof(a)); } }; int path[6][3], pi; bool dfs(M a, int step) { if (step >= n && a.empty()) return 1; else if (step >= n) return 0; else if (a.empty()) return 0; for (int j = 1; j <= 5; j++) for (int i = 7; i >= 1; i--) if (a[i][j]) { if (j <= 4 && a[i][j] != a[i][j + 1] && dfs(a.drag(i, j, 1), step + 1)) return path[++pi][0] = i, path[pi][1] = j, path[pi][2] = 1; if (j >= 2 && !a[i][j - 1] && dfs(a.drag(i, j, -1), step + 1)) return path[++pi][0] = i, path[pi][1] = j, path[pi][2] = -1; } return 0; } int main() { scanf("%d", &n); M a; for (int i = 1, t, ti = 0; ti = 0, i <= 5; i++) while(scanf("%d", &t), t) a[8 - (++ti)][i] = t; if (dfs(a, 0)) { for (int i = pi; i >= 1; i--) printf("%d %d %d\n", path[i][1] - 1, 7 - path[i][0], path[i][2]); } else puts("-1"); return 0; }
魔改版(大霧)
#include <cstdio> #include <cstring> #include <cstdlib> #include <ctime> int n; struct M { int a[8][6]; inline bool down(int x, int y) { int b[8]; for (register int i = 1; i <= 7; i++) b[i] = a[i][y]; for (register int i = x; i >= 1; i--) if (b[i]) { for (register int j = i; j >= 1; j--) a[x + (j - i)][y] = b[j], a[j][y] = 0; return 1; } return 0; } inline bool fall() { bool flag = 0; for (register int i = 1; i <= 5; i++) for (register int j = 7; j >= 2; j--) if (!a[j][i] && !(flag |= down(j, i))) break; return flag; } inline void del() { int b[8][6]; memcpy(b, a, sizeof(a)); for (register int i = 1; i <= 7; i++) for (register int j = 1; j <= 5; j++) if (a[i][j]) { if(j >= 2 && j <= 4 && a[i][j - 1] == a[i][j] && a[i][j + 1] == a[i][j]) b[i][j] = b[i][j - 1] = b[i][j + 1] = 0; if(i >= 1 && i <= 6 && a[i - 1][j] == a[i][j] && a[i + 1][j] == a[i][j]) b[i][j] = b[i - 1][j] = b[i + 1][j] = 0; } memcpy(a, b, sizeof(b)); } inline bool empty() { for (register int i = 1; i <= 7; i++) for (register int j = 1; j <= 5; j++) if (a[i][j]) return 0; return 1; } M update() { do del(); while(fall()); return *this; } M drag(int x, int y, int g) { M nxt = *this; nxt[x][y] ^= nxt[x][y + g]; nxt[x][y + g] ^= nxt[x][y]; nxt[x][y] ^= nxt[x][y + g]; nxt.update(); return nxt; } M print() { puts("\033c"); printf(" "); for (int i = 0; i <= 4; i++) printf("%2d", i); puts(""); for (int i = 1; i <= 7; i++) { printf("%d", 7 - i); for (int j = 1; j <= 5; j++) printf("\033[3%d;7m \033[0m", a[i][j]); puts(""); } return *this; } bool isend() { int vis[10] = {0}; for (int i = 1; i <= 7; i++) for (int j = 1; j <= 5; j++) vis[a[i][j]]++; for (int i = 1; i <= 10; i++) if (vis[i] >= 3) return 0; return 1; } bool operator==(M b) { for (register int i = 1; i <= 7; i++) for (register int j = 1; j <= 5; j++) if (a[i][j] != b[i][j]) return 0; return 1; } int* operator[](int i) { return a[i]; } M () { memset(a, 0, sizeof(a)); } M (int v) { memset(a, v, sizeof(a)); } }; int main() { srand(time(0)); M a(0); for (int i = 1; i <= 7; i++) for (int j = 1; j <= 7; j++) a[i][j] = rand() % 4; a.update().print(); if (a.isend()) return printf("0 step\n"), 0; int step = 0; while(1) { int x, y, g; a.print(); scanf("%d%d%d", &x, &y, &g); if (x >= 1 && x <= 7 && y >= 1 && y <= 5 && (g == -1 || g == 1)) { a = a.drag(7 - y, x + 1, g).print(); step++; } if (a.isend()) break; } printf("%d%s\n", step, step <= 1 ? "" : "s"); return 0; }