博弈问题总集第六类----非Nim游戏

来源:互联网 发布:json转化为byte数组 编辑:程序博客网 时间:2024/06/05 22:52

翻硬币

题目:

[HDU3537] Daizhenyang’s Coin

题解:

先放一个特别好的up,有心情再看吧
这道题是约束6,直接结论跑
坑点:后面给的正面朝上的坐标还有重复?

代码:

#include <map>#include <cstdio>using namespace std;bool pd(int x){    int cnt=0;    while (x) {if (x&1) cnt++;x>>=1;}    if (cnt%2) return 0;else return 1;}int find(int x){    if (pd(x)) return x+1;    else return x;}int main(){    int n,a;    while (~scanf("%d",&n))    {        map<int,bool>mp;int ans=0;        for (int i=1;i<=n;i++)         {            scanf("%d",&a);            if(mp[a]==0)               ans^=find(2*a);            mp[a]=1;        }        if (ans) printf("No\n");else printf("Yes\n");    }}

删边游戏

它指的是给出一棵树,每次可以在树上删掉一条边,和根节点脱离的部分整个被删掉,最后不能操作的人输。
结论:叶子节点的SG值为0,其它节点的SG值为子树SG值+1 的异或值,最后判断根节点的值

1、题目:

[HDU3094] A tree game

题解:

按照结论做就好了

代码:

#include <cstdio>#include <cstring>using namespace std;const int N=1e5;int tot,nxt[N*2],point[N],v[N*2],sg[N];void addline(int x,int y){    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}void dfs(int x,int fa){    int k=0;    for (int i=point[x];i;i=nxt[i])      if (v[i]!=fa)      {        dfs(v[i],x);        k^=sg[v[i]]+1;      }    sg[x]=k;}int main(){    int T,n;    scanf("%d",&T);    while (T--)    {        tot=0;memset(point,0,sizeof(point));        scanf("%d",&n);        for (int i=1;i<n;i++)        {            int x,y;            scanf("%d%d",&x,&y);            addline(x,y);        }        dfs(1,0);        if (sg[1]) printf("Alice\n");else printf("Bob\n");    }}

2、题目:

[POJ3710] Christmas Game

题解:

出现了,但是环我不会呀,还是先转化成树吧
对于无向图的删边游戏有如下定理性质:

  1. 对于长度为奇数的环,它的SG值为1;对于长度为偶数的环,它的SG值为0;
  2. 叶子节点的SG值为0;中间节点的SG值为它的所有子节点的SG值+1后的异或和。

然后这个题就可以做啦,缩点一波然后跑就行了

A了之后觉得这个题的数据真是有毒,不仅重边,有了环的点还有重任
不要忘记给已经不用的点出栈

代码:

#include <cstdio>#include <cstring>using namespace std;const int N=105;int tot,nxt[1505],point[N],v[1505],stack[N],sg[N],top,vis[N];void addline(int x,int y){    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}void clear(){    tot=top=0;memset(point,0,sizeof(point));    memset(vis,-1,sizeof(vis));memset(sg,0,sizeof(sg));}void dfs(int x,int fa){    bool fff=0;    vis[x]=1; stack[++top]=x;    for (int i=point[x];i;i=nxt[i])      {        if (v[i]==fa && !fff){fff=1; continue;}        if (vis[v[i]]==1)         {            int now=0,cnt=1;            while (stack[top]!=v[i])              vis[stack[top--]]=0,cnt++;            if (cnt%2) sg[v[i]]=1;        }        else if (vis[v[i]]==-1)        {            dfs(v[i],x);            if (vis[v[i]]) sg[x]^=sg[v[i]]+1;        }      }    if (vis[x]) top--;}int main(){    int n,m,k;    while (~scanf("%d",&n))    {        int kt=0;        for (int i=1;i<=n;i++)        {            clear();            scanf("%d%d",&m,&k);            for (int j=1;j<=k;j++)            {                int x,y;scanf("%d%d",&x,&y);                addline(x,y);            }            dfs(1,0);            kt^=sg[1];        }        if (kt) printf("Sally\n");else printf("Harry\n");    }}