HDU 1524 A Chess Game (SG函数模板题)

来源:互联网 发布:数据库体育信息管理 编辑:程序博客网 时间:2024/06/02 16:53
题意:在一个有向无环图上有n个顶点,每一个顶点都只有一个棋子,有两个人,每次根据这个图只能将任意一颗

棋子移动一步

,如果到某一步玩家不能移动时,那么这个人就输.


分析:本题是最典型的有向无环图的博弈,利用dfs把所有顶点的SG值都计算出来,然后对每个棋子的SG值进行

异或运算,如果为0就是先手必败,否则就是先手必胜.

如果某个人移动到出度为0的顶点,那么他必败,在这里首先介绍一下什么是SG函数.


Sprague-Grudy定理:

令N = {0, 1, 2, 3, ...} 为自然数的集合。Sprague-Grundy 函数给游戏中的每个状态分配了一个自然数。

结点v的Grundy值等于没有在v的后继的Grundy值中出现的最小自然数.

形式上:给定一个有限子集 S ⊂ N,令mex S(最小排斥值)为没有出现在S中的最小自然数。定义mex(minimal

excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}

=3、mex{2,3,5}=0、mex{}=0。

对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Garundy函数g如下:g(x)=mex{ g(y) | y是x

的后继 }。

性质:

(1)所有的终结点所对应的顶点,其SG值为0,因为它的后继集合是空集——所有终结点是必败点(P点即先

手必败点)。

(2)对于一个g(x)=0的顶点x,它的所有后继y都满足g(y)!=0——无论如何操作,从必败点(P点)都只能进

入必胜点(N点)//对手走完又只能把N留给我们。

(3)对于一个g(x)!=0的顶点,必定存在一个后继点y满足g(y)=0——从任何必胜点(N点)操作,至少有一

种方法可以进入必败点(P点)//就是那种我们要走的方法。


而求整个SG函数值的过程就是一个对有向无环图进行深搜过程.
其次解释一下为什么要异或。
这需要了解下Nim博弈,事实上我们可以利用SG函数转成Nim博弈。

Nim问题模型

然后解决它的思路是这样的

那么知道Nim博弈如何解决,我们如何将SG巧妙第转换为nim呢?

以上内容均来自《挑战程序设计竞赛》

所以,问题就解决啦,先DFS出SG函数(注意要用记忆化搜索哦,否则很容易超时),然后算出所有SG的异或值即可。

#include<iostream>#include<vector>#include<cstdio>using namespace std;const int maxn=1005;vector<int>G[maxn];int n,dp[maxn];int dfs(int u){    if(dp[u]!=-1) return dp[u];    int vis[maxn];    fill(vis,vis+n,0);    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        dp[v]=dfs(v);        vis[dp[v]]=1;    }    for(int i=0;i<n;i++)        if(vis[i]==0) return i;}int main(){    //freopen("in.txt","r",stdin);    while(cin>>n)    {        for(int i=0;i<=n;i++) G[i].clear(),dp[i]=-1;//清空邻接矩阵以及初始化记忆化数组        for(int i=0;i<n;i++)        {            int m,x;            cin>>m;            while(m--)            {                cin>>x;                G[i].push_back(x);//用邻接表存有向图            }        }        int q;        while(cin>>q,q)        {            int x,f=0;            while(q--)            {                cin>>x;                f^=dfs(x);//算出所有数异或的结果            }            if(f) cout<<"WIN"<<endl;            else cout<<"LOSE"<<endl;        }    }    return 0;}


0 0
原创粉丝点击