• 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
    ", 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("33c");
    		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("33[3%d;7m  33[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
    "), 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
    ", step, step <= 1 ? "step" : "steps");
    	return 0;
    }
    
  • 相关阅读:
    【Docker 命令】- top命令
    笛卡尔的情书
    thinkphp5.0 中使用第三方无命名空间的类库
    配置thinkphp3.2 404页面
    svn取消文件夹关联的方法(svn取消关联)
    wamp php.ini 配置的坑
    meta标签中的http-equiv属性使用介绍
    META http-equiv="refresh" 实现网页自动跳转
    关于onclick的执行原理
    redis启动出错Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
  • 原文地址:https://www.cnblogs.com/youxam/p/p1312.html
Copyright © 2020-2023  润新知