博弈论初探----DAG上的NIM

本文介绍了一种基于有向无环图(DAG)的游戏策略分析方法。通过构建DAG并利用拓扑排序算法,判断先手玩家是否拥有必胜策略。代码实现详细展示了如何存储图结构、计算每个节点的状态,并最终确定起始位置的胜负。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给定一个DAG,起点1出有一个棋子,先手后手依次将他向出边移动,最先无法移动的人输,求先手是否必胜。
//因为只要能转移到任意的对手的必败态,便为必胜态,反之为必败态,故只会有必胜/必败态存在。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define maxn 10010
#define maxm 10010
using namespace std;

struct Edge{
    int u;
    int v;
    Edge *next;
} edge[maxm];

bool win[maxn];
int n, m;
int out_edge[maxn];
int topo_queue[maxn], q_end = 0, q_begin = 0;
Edge *V[maxn];

int main() {
    cin >> n >> m;
    memset(out_edge, 0, sizeof(out_edge));
    for (int i = 1; i <= m ; i++) {
        cin >> edge[i].u >> edge[i].v;
        edge[i].next = V[edge[i].v];
        V[edge[i].v] = &edge[i];
        out_edge[edge[i].u]++;
    }//邻接表储存,同时记录出度。 
    for(int i = 1; i <= n; i++)
        if(!out_edge[i]) topo_queue[q_end++] = i;//将所有出度为0的点加入处理队列中 
    for(int i = 0; i < q_end; i++)
        win[i] = false;                         //所有点初始为先手无法必胜,因先手到达无法走的点即败 
    while(q_begin < q_end) {
        int i = topo_queue[q_begin++];
        win[i] = !win[i];                       //win[i]表示以i点位起点,先手是否必胜,这里将之前表示的能否到达先手必败态的节点 反转为先手是否必胜
        for(Edge *e = V[i]; e; e = e->next) {   
            if(--out_edge[e->u] == 0) {         
                win[e->u] = win[i] || win[e->u];//只要以此节点为起点走能转移到任意一个先手必胜态的起点,此节点先手必败。
                                                // 这里记录的是能否到达一个先手必胜态的起点。当此节点出队时再反转结果

                topo_queue[q_end++] = e->u;     
            }
        } //toposort删边过程 
    }     //toposort过程 
    if(win[1]) cout << "win";
        else cout << "lose";
    return 0;
}

ps:最近代码风格变化的略快略多啊。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值