P1312 Mayan游戏 题解
思路很简单, 模拟, 搜索
注意向左交换和向右交换其实是等价的, 所以不用枚举向左交换(因为优先向右交换)
但是如果当前枚举的块左边为空, 不存在过从左边向右交换的情况, 所以这种情况要额外判断, 多一个向左交换的搜索子树
代码
#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 = 1; i <= 5; i++) printf("%2d", i);
puts("");
for (int i = 1; i <= 7; i++) {
printf("%d", 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() % 5;
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(x, y, g).print();
step++;
}
if (a.isend()) break;
}
printf("%d %s\n", step, step <= 1 ? "step" : "steps");
return 0;
}