怀旧游戏 题解(逆向bfs打表博弈)

题目链接

题目思路

一直不太会这种有环的博弈打表,今天学到了新知识

处理出每个点的前驱节点,找出所有必败点,然后转移,确定状态后再放入队列,太秒了

\(f[i][j][k][l]\) 表示先手手上的数字是 \(i, j\),后手手上的数字是 \(k, l\) 时,先手的胜负情况。初始先手必败的情况比较好处理(\(k\)\(l\) 是 0,意味着先手已经输了),接着反向 bfs,对于一个状态,如果它存在一个先手必败的后续状态,则这个状态先手必胜;如果它所有的后续状态都是先手必胜的,则这个状态先手必败。
对于无法确定胜负的状态,都是平局。

直接放官方题解和官方代码

代码

#include <bits/stdc++.h>

using namespace std;

int f[11][11][11][11], c[10001][4], b[11][11][11][11];
int test, a1, a2, b1, b2;

struct node {
	int a1, a2, b1, b2;
};

vector<node> a[11][11][11][11];

int main() {
	for (int i = 1; i <= 9; i++)
		for (int j = 1; j <= 9; j++)
			for (int k = 1; k <= 9; k++)
				for (int l = 1; l <= 9; l++) {
					node res;
					res.a1 = i; res.a2 = j;
					res.b1 = k; res.b2 = l;
					a[k][l][(i + j) % 10][j].push_back(res);
					a[k][l][(i + k) % 10][j].push_back(res);
					a[k][l][(i + l) % 10][j].push_back(res);
					a[k][l][i][(j + i) % 10].push_back(res);
					a[k][l][i][(j + k) % 10].push_back(res);
					a[k][l][i][(j + l) % 10].push_back(res);
				}
	memset(f, 0, sizeof(f));
	int head = 0;
	for (int i = 1; i <= 9; i++)
		for (int j = 1; j <= 9; j++)
			for (int k = 1; k <= 9; k++) {
				f[i][j][k][0] = 2;
				c[++head][0] = i; c[head][1] = j;
				c[head][2] = k; c[head][3] = 0;
				f[i][j][0][k] = 2;
				c[++head][0] = i; c[head][1] = j;
				c[head][2] = 0; c[head][3] = k;
			}
	for (int l = 1; l <= head; l++) {
		int a1 = c[l][0], a2 = c[l][1], b1 = c[l][2], b2 = c[l][3];
		int v = f[a1][a2][b1][b2];
		if (v == 2) {
			for (auto i : a[a1][a2][b1][b2])
				if (!f[i.a1][i.a2][i.b1][i.b2]) {
					//printf("!\n");
					f[i.a1][i.a2][i.b1][i.b2] = 1;
					c[++head][0] = i.a1; c[head][1] = i.a2;
					c[head][2] = i.b1; c[head][3] = i.b2;
				}
		} else {
			for (auto i : a[a1][a2][b1][b2])
				if (!f[i.a1][i.a2][i.b1][i.b2]
				&& ++b[i.a1][i.a2][i.b1][i.b2] == 6) {
					f[i.a1][i.a2][i.b1][i.b2] = 2;
					c[++head][0] = i.a1; c[head][1] = i.a2;
					c[head][2] = i.b1; c[head][3] = i.b2;
				}
		}
	}
	scanf("%d", &test);
	for (; test--; ) {
		scanf("%d%d%d%d", &a1, &a2, &b1, &b2);
		if (f[a1][a2][b1][b2] == 1)
			printf("Alice\n");
		else
			if (f[a1][a2][b1][b2] == 2)
				printf("Bob\n");
			else
				printf("Tie\n");
	}
}

posted @ 2021-08-07 21:56  hunxuewangzi  阅读(51)  评论(0编辑  收藏  举报