博弈论题目总结(三)——组合游戏进阶

第二波题目大多都是sg组合游戏的基本变形,是对游戏规则的小改动。容易提取出SG函数的模型,且SG函数的规律也比较简单

而本文的题目需要较多的模型转化思想

但博弈论的精髓还是打表

 

翻硬币游戏

一条直线上有很多硬币,有的正面朝上,有的反面朝上,每次可以翻一些硬币,但最右边的硬币必须由正变反,不能操作者输

翻硬币可能会有奇奇怪怪的要求,一次翻好几个,一次翻连续的几个

结论:正面朝上的石子之间互不影响,设正面朝上是1,反面朝上是0,那么SG(0101001)=SG(01)^SG(0001)^SG(0000001)

证明见论文

 

树形删边游戏

SG(u)=xor{SG(v)+1}

证明见jzh神犇的论文

 

POJ 3710 Christmas Game

环怎么处理啊?

一个奇环可以分成等长的两条链,SG函数值为0,其他后继状态的SG函数值均>1,故奇环的SG函数值为1

一个偶环只能分成异奇偶的两条链,SG函数值均>0,故奇环的SG函数值为0

tarjan边双缩点搞一下就行了

博弈论题目总结(三)——组合游戏进阶
  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define N1 105
  6 #define M1 505
  7 #define ll long long 
  8 #define dd double
  9 using namespace std;
 10 const dd eps=1e-7;
 11 
 12 template <typename _T> void read(_T &ret)
 13 {
 14     ret=0; _T fh=1; char c=getchar();
 15     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
 16     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
 17     ret=ret*fh;
 18 }
 19 struct Edge{
 20 int to[M1*2],nxt[M1*2],val[M1*2],head[N1],cte;
 21 void ae(int u,int v,int w)
 22 {
 23     cte++; to[cte]=v; nxt[cte]=head[u];
 24     head[u]=cte; val[cte]=w;
 25 }
 26 }e,E;
 27 
 28 int T,n,m;
 29 int low[N1],dfn[N1],use[N1],stk[N1],dad[N1],sum[N1],tim,num,tp;
 30 void tarjan(int x,int fa)
 31 {
 32     int j,v;
 33     low[x]=dfn[x]=++tim; stk[++tp]=x; use[x]=1;
 34     for(j=e.head[x];j;j=e.nxt[j])
 35     {
 36         v=e.to[j]; if(e.val[j]==fa) continue;
 37         if(!dfn[v]){
 38             tarjan(v,e.val[j]);
 39             low[x]=min(low[x],low[v]);
 40         }else if(use[x]){
 41             low[x]=min(low[x],dfn[v]);
 42         }
 43     }
 44     if(low[x]==dfn[x])
 45     {
 46         num++;
 47         while(stk[tp]!=x){ use[stk[tp]]=0; dad[stk[tp]]=num; sum[num]++; tp--; }
 48         use[x]=0; dad[x]=num; sum[num]++; tp--;
 49     }
 50 }
 51 
 52 void rebuild()
 53 {
 54     int i,j,v;
 55     for(i=1;i<=n;i++)
 56     {
 57         for(j=e.head[i];j;j=e.nxt[j])
 58         {
 59             v=e.to[j];
 60             if(dad[i]!=dad[v]) 
 61                 E.ae(dad[i],dad[v],0);
 62         }
 63     }
 64 }
 65 
 66 int sg[N1],de;
 67 void dfs(int x,int fa)
 68 {
 69     int j,v;
 70     for(j=E.head[x];j;j=E.nxt[j])
 71     {
 72         v=E.to[j]; if(v==fa) continue;
 73         dfs(v,x); sg[x]^=sg[v]+1;
 74     }
 75     if(sum[x]>1 && (sum[x]&1)) sg[x]^=1;
 76 }
 77 
 78 void init()
 79 {
 80     memset(sg,0,sizeof(sg)); memset(low,0,sizeof(low)); 
 81     memset(sum,0,sizeof(sum)); memset(dfn,0,sizeof(dfn)); 
 82     memset(dad,0,sizeof(dad)); memset(use,0,sizeof(use)); 
 83     memset(&e,0,sizeof(e));  memset(&E,0,sizeof(E)); 
 84     tim=0; tp=0; num=0;
 85 }
 86 
 87 int N;
 88 int main()
 89 {
 90     int i,j,x,y;
 91     while(scanf("%d",&N)!=EOF) {
 92     
 93     int ans=0;
 94     while(N--)
 95     {
 96         init(); read(n); read(m);
 97         for(i=1;i<=m;i++)
 98         {
 99             read(x); read(y); e.ae(x,y,i); e.ae(y,x,i);
100         }
101         for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1);
102         rebuild();
103         dfs(dad[1],-1);
104         ans^=sg[dad[1]];
105     }
106     if(ans) puts("Sally"); else puts("Harry");
107         
108     }
109     return 0;
110 }
View Code

 

上一篇:利用py批量下载文件,并且给文件分类!


下一篇:利用py批量下载文件,并且给文件分类!