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;
}
posted @ 2020-07-29 15:29  YouXam  阅读(201)  评论(5编辑  收藏  举报