基础博弈专题
感觉,目前主要是能够将具体的题目转化为某一种博弈类型,这样根据类型来做,会好很多。
首先,是比较基础的
巴什博奕(Bash Game):
根据这三个性质去推理的话,下面这几道题目应该可以很快解决
(1) 所有终结点是必败点(P点);
(2) 从任何必胜点(N点)操作,至少有一种方法可以进入必败点(P点);
(3)无论如何操作, 从必败点(P点)都只能进入必胜点(N点).
hdu1846
#include<iostream> using namespace std; int main() { int n,m,cas; scanf("%d",&cas); while(cas--) { scanf("%d %d",&n,&m); if(n<=m) puts("first"); else if(n%(m+1)==0) puts("second"); else puts("first"); } return 0; }
hdu 2147
#include<iostream> using namespace std; int main() { int n,m; while(scanf("%d %d",&n,&m)==2&&(n||m)) { if(n%2==1 && m%2==1) puts("What a pity!"); else puts("Wonderful!"); } return 0; }
hdu2149
#include<iostream> using namespace std; int main() { int m,n; while(scanf("%d %d",&m,&n)==2) { if(n>=m) { for(int i=m;i<n;i++) printf("%d ",i); printf("%d\n",n); continue; } int flag=0; for(int i=1;i<=n;i++) { if(m-i<=n) continue; if((m-i)%(n+1)==0) { if(!flag) printf("%d",i),flag=1; else printf(" %d",i); } } if(flag)puts(""); else puts("none"); } return 0; }
hdu2188
#include<iostream> using namespace std; int main() { int n,m,cas; scanf("%d",&cas); while(cas--) { scanf("%d %d",&n,&m); if(n<=m) { puts("Grass"); continue; } if(n%(m+1)==0) puts("Rabbit"); else puts("Grass"); } return 0; }
接下来是
(二)威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同
时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
嘿嘿,没做过类型的题目。
再接下来,是
比较重点的
(三)尼姆博奕(Nimm Game):有三堆各若干个物品,两个人轮流从某一堆取任意多的
物品,规定每次至少取一个,多者不限,最后取光者得胜。
主要涉及到了异或操作,关于这方面,感觉这篇博文介绍的还不错http://blog.sina.com.cn/s/blog_8f06da990100uwl1.html
hdu1849
#include<iostream> #include<algorithm> using namespace std; int main() { int a,n; while(scanf("%d",&n)==1 && n) { a=0; int b; for(int i=0;i<n;i++) { scanf("%d",&b); a^=b; } if(a!=0) puts("Rabbit Win!"); else puts("Grass Win!"); } return 0; }
hdu1850
#include<stdio.h> int main() { int n,s[110],i,sum,count; while(scanf("%d",&n)!=EOF&&n) { sum=0;count=0; for(i=0;i<n;i++) { scanf("%d",&s[i]); sum=sum^s[i]; } for(i=0;i<n;i++) { if(s[i]>(sum^s[i])) count++; } printf("%d\n",count); } return 0; }
再接下来就是博弈的经典所在了,关于sg函数
同样,在上面的博文里面介绍的很详细了
hdu1848 ( Fibonacci again and again ) sg函数与Nim博弈的组合
#include<iostream> #include<algorithm> using namespace std; int fib[1010],a[20],hash1[1010],sg[1010]; void init() { a[0]=a[1]=1; a[2]=2; memset(fib,0,sizeof(fib)); fib[1]=fib[2]=1; for(int i=3;a[i-1]<=1000;i++) { a[i]=a[i-1]+a[i-2]; fib[a[i]]=1; } } void Get_sg() { for(int i=0;i<=3;i++) sg[i]=i; for(int i=4;i<=1000;i++) { memset(hash1,0,sizeof(hash1)); for(int j=1;j<=i;j++) if(fib[j]) hash1[sg[i-j]]=1; for(int k=0;k<=i;k++) if(!hash1[k]) { sg[i]=k; break; } } } int main() { init(); Get_sg(); int n,m,p; while(scanf("%d %d %d",&n,&m,&p)==3&& (m||n||p)) { if((sg[n]^sg[m]^sg[p])!=0) puts("Fibo"); else puts("Nacci"); } return 0; }