目录
一,区字棋
二,不败策略
三,有向有环图分析
1,最长非零链
2,详细有向有环图
也叫憋死牛棋。
规则:
棋盘一共只有5个点,双方各2个棋子,还有一个空格。
先手必须移动左边的棋子,之后没有限制,2个棋子任意一个移动到空格皆可。
无法移动者判负。
因为失败的阵型是固定的,要么2个都在上面,要么2个都在下面,只有这样才有可能被堵住。
所以不败策略也很简单,任意状态下,轮到任意方行动时,都至少有1种行动方法,不会走到固定的失败阵型,这就是不败策略了。
用博弈论分析,这个属于有向有环图游戏,上面的不败策略其实就是说,该有向图的等价图中,最长的非零链的长度为2,即1个回合。
我们来验证一下。
(1)给所有状态编号
假设轮到某一方行动时,他的2个棋子分别在i,j,空格在k,那么我们编号为i*25+j*5+k,其中0<=i,j,k<=5
所有状态的编号都在0到124之间,但其中有小部分是非法状态(ijk重复),合法状态只有60种。
考虑到2个棋子相同的话,实际上只有30个不同的合法状态。
(2)构建有向图
int getId(int i, int j, int k) { return i * 25 + j * 5 + k; } int getId(vectorv) { int i = v[0], j = v[1], k = v[2]; return i * 25 + j * 5 + k; } vector getIjk(int id) { return vector {id / 25, id % 25 / 5, id % 5}; } bool isConnect(int x, int y) { if (x == 2 || y == 2)return true; if (x > y)x ^= y ^= x ^= y; if (x == 0)return y < 4; return x==3; } vector reverseTurn(int i, int j, int k) { int ni = 0, nj = 0; while (ni == i || ni == j || ni == k)ni++; while (nj == i || nj == j || nj == k||nj==ni)nj++; return vector {ni, nj, k}; } vector getNext(int id) { auto v = getIjk(id); int i = v[0], j = v[1], k = v[2]; vector ans; if (isConnect(k, i))ans.push_back(getId(reverseTurn(k, j, i))); if (isConnect(k, j))ans.push_back(getId(reverseTurn(i, k, j))); return ans; } map > bfs(int id) { queue q; q.push(id); map visit; visit[id] = 1; map >ans; while (!q.empty()) { int t = q.front(); q.pop(); auto v = getNext(t); ans[t] = v; for (auto x : v) { if (visit[x])continue; visit[x] = 1; q.push(x); } } return ans; }
(3)调用有向有环图游戏的模板,统计最长非0链
int main() { int id = getId(3, 4, 0); map> g = bfs(id); map out; map >rg; map s; for (auto gi : g) { out[gi.first] = gi.second.size(); if (out[gi.first] == 0)s[gi.first] = -1; for (auto x : gi.second) { rg[x].push_back(gi.first); } } JudgeDirectedCyclicGraph::solve(out, rg, s); return 0; }
输出:
fromV1ToV2
fromV2ToV1
所以,最长非零链长度为2
其中,9和96是负节点,7,35,73,97是胜节点,其他22个节点都是平节点。
本来应该有30个节点,但是有2个节点是不可达的,分别是(0,2,1)和(2,3,4)
上一篇:免费chartGPT网站汇总--