区字棋中的最长非0链

目录

一,区字棋

二,不败策略

三,有向有环图分析

1,最长非零链

2,详细有向有环图


一,区字棋

也叫憋死牛棋。

规则:

棋盘一共只有5个点,双方各2个棋子,还有一个空格。

先手必须移动左边的棋子,之后没有限制,2个棋子任意一个移动到空格皆可。

无法移动者判负。

二,不败策略

因为失败的阵型是固定的,要么2个都在上面,要么2个都在下面,只有这样才有可能被堵住。

所以不败策略也很简单,任意状态下,轮到任意方行动时,都至少有1种行动方法,不会走到固定的失败阵型,这就是不败策略了。

三,有向有环图分析

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(vector<int>v) {
    int i = v[0], j = v[1], k = v[2];
    return i * 25 + j * 5 + k;
}
vector<int> getIjk(int id) {
    return vector<int>{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<int>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<int>{ni, nj, k};
}
vector<int> getNext(int id) {
    auto v = getIjk(id);
    int i = v[0], j = v[1], k = v[2];
    vector<int>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<int, vector<int>> bfs(int id)
{
    queue<int>q;
    q.push(id);
    map<int, int>visit;
    visit[id] = 1;
    map<int, vector<int>>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<int, vector<int>> g = bfs(id);
    map<int, int> out;
    map<int, vector<int>>rg;
    map<int, int>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

2,详细有向有环图

其中,9和96是负节点,7,35,73,97是胜节点,其他22个节点都是平节点。

本来应该有30个节点,但是有2个节点是不可达的,分别是(0,2,1)和(2,3,4)

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值