HDU组合游戏与博弈论入门小结(未完
来源:互联网 发布:手机怎么添加wifi网络 编辑:程序博客网 时间:2024/04/30 02:22
1.组合游戏的定义:
组合游戏是一个常见的概念,它是是满足这样一些条件的游戏:
1) 游戏有2名参与者,每个人都采用对自己最有利的策略。
2) 参与者操作时可以的操作时将游戏从当前状态改变为另一状态。
3) 参与者轮流进行操作,每个玩家可选择的状态是固定的,没有随机成分
4) 在游戏出于某状态,当前参与者不能进行操作时,游戏结束。此时参照规则决定胜负。
5) 无论参与者做出怎样的操作游戏在有限部数之内结束(没有平局),所以组合游戏必然是一个无环图。
组合游戏也可以用一个有向图来表示 G=(X,F)X为游戏的状态集合F(X)为X可以到达的状态集合,而结束状态均宣布当前参与者失败。
这类博弈问题还有若干分类。
规定移动最后一步的游戏者胜的规则叫做Normal Play Rule。
规定移动最后一步的游戏者输的规则叫做Misere Play Rule 也称Anti-SG games。
此外,对于游戏的双方,如果二者博弈的规则相同,那么称这类游戏是impartial games否则称为partizan games 。
实际上,解决partizan games的方法和普通的SG games是有区别的,一般会采用动态规划或者surreal number。
2.必胜局面
组合游戏的必胜状局面定义为当前玩家有策略能使无论对手做什么操作也可以保证自己胜利的状态。
1) 结束状态的性质由规则决定。
2) 一个非结束状态,如果它能到达任何必败状态,那么它是必胜状态,否则它就是必败状态。
3.Sprague-Grundy 函数
它是定义在组合游戏状态上的函数,用g (X)表示X状态的函数值。
定义为:
g (X)= min{n| n∈N ,n≠ for y∈F(x)}
形象的说就是X的函数值为与X所能到达的任意点函数值不同的最小自然数。
我想细心的读者已经发现g (X)=0当且仅当X为必败状态,这用其定义很容易验证:
1) 当X为结束状态时,由于g (X)=0它是必败状态。
2) 当X不是结束状态时,如果它能到达必败状态,那么g (X)>0,X是必胜状态。
3) 如果X不是结束状态且它到达的所有状态未必败状态,那么g (X)=0它是必败状态。
(一)巴什博奕(Bash Game):
只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个.最后取光者得胜.
n = (m+1)r+s , (r为任意自然数,s≤m), 即n%(m+1) != 0, 则先取者肯定获胜。
巴什博弈还是很好理解的,以你是先手的角度考虑,每一局你都必须构建一个局势,每次都留给对手m+1的倍数个物品。所以不只是取物品中的博弈可以用到巴什定理,还可以是报数之类的,看谁先报到100.并且每次报的数必须是1~10(包括1跟10),那么你每次都应该留给对手剩下的报数个数为11的倍数。如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。
题目:
HDU1846:常规做法
<span style="font-size:14px;">#include<cstdio>int main(){ int m,n,i,c; while(~scanf("%d",&c)) { while(c--) { scanf("%d%d",&m,&n); bool flag=true; if(m%(n+1)==0) flag=false; if(flag) printf("first\n"); else printf("second\n"); } } return 0; } </span>
HDU1847:由于可以抽二的倍数 所以只判断2+1=3就好
#include<cstdio>int main(){ int n; while(~scanf("%d",&n)) { if(n%3==0) printf("Cici\n"); else printf("Kiki\n"); } return 0;}
HDU2147:把棋盘的左下角看成(1,1)那么起始点就是(n,m),最后谁能得到(1,1)这个点谁就胜,可以看出只要先抢到(奇数,奇数)接下来无论对方怎么走都会至少有一个坐标是偶数,那么对方就一定会败,先者有三种走发(n-1,m),(n,m-1),(n-1,m-1)只有m和n都是奇数的时候第一步走不出来(奇数,奇数)其余的(只要有一个是偶数)就肯定会得到必胜态(奇,奇),就会赢。
#include<iostream>using namespace std;int main(){ int n,m; while(cin>>n>>m,m+n) { puts((n%2&&m%2)?"What a pity!":"Wonderful!"); } return 0;}
HDU2149:基本做法
#include<cstdio>int main(){ int n,m; while(~scanf("%d%d",&m,&n)) { if(m%(n+1)==0) printf("none\n"); else if(n>m) { printf("%d",m); for(int i=m+1;i<=n;i++) { printf("% d",i); } printf("\n"); } else printf("%d\n",m%(n+1)); } return 0;}
HDU2188:基本做法
#include<cstdio>int main(){ int c,n,m; while(~scanf("%d",&c)) { while(c--) { scanf("%d%d",&n,&m); if(n%(m+1)==0) printf("Rabbit\n"); else printf("Grass\n"); } }}
HDU2897:巴什博弈的变形 假设先取者为A,后取者为B,初始状态下有石子n个,除最后一次外其他每次取得石子个数必须在[p,q]之间。
若当前石子共有n =(p+q)* r个,A必胜,策略为A第一次取q个,以后每次若B取K个,A取(p+q-k)个,如此下去最后必剩下p个给B,所以A必胜。
若n =(p+q)*r+s个(1<s<=p)B胜,策略为每次取石子活动中,若A取k个,则B去(p+q-k)个,最后剩下s个给A,此时s<= p,A一次取完,B胜。
若n =(p+q)* r+s个(p<s<=q)A胜,策略为A第一次取t(1<s–t<= p)个,以后每次B取k个,则A取(p+q-k)个,那么最后留下1<s-t<=p给B,则A胜。
#include<cstdio>int main(){ int n,p,q; while(~scanf("%d%d%d",&n,&p,&q)) { if(n%(q+p)>0&&n%(q+p)<=p) printf("LOST\n"); else printf("WIN\n"); } return 0;}理解了bash的规则这种题还是很水的
(二)威佐夫博奕(Wythoff Game)
有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。用(a[k],b[k])(a[k] ≤ b[k] ,k=0,1,2,...,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0)甲输,称这种局势为奇异局势。前几个奇异局势是:(0,0),(1,2),(3,5),(4,7),(6,10),(8,13),(9,15),(11,18),(12,20)。
仔细观察规律可以发现可以看出:
#include<stdio.h>#include<math.h>int main(){ int n,m,temp,k; while(~scanf("%d%d",&n,&m)) { if(n<m) { temp=n; n=m; m=temp; } k=n-m; n=(int)(k*(1.0+sqrt(5.0))/2.0); if(n==m) printf("0\n"); else printf("1\n"); } return 0;}
HDU2177:前一题的升级版
#include<stdio.h>#include<string.h>#include<math.h>#define MAX 99999999 int main(){int n,m,t,i;double q;q=(sqrt(5.0)+1)/2.0;while(~scanf("%d%d",&n,&m)&&(n||m)){t=(int)(q*(m-n)); if(n!=t){printf("1\n");printf("%d %d\n",t,m-(n-t)); int x;for(i=0;i<=m;i++){x=m-i; if(x>n) {if( (int)(q*(x-n))==n ) printf("%d %d\n",n,x);}else if(x<n){if( (int)(q*(n-x))==x )printf("%d %d\n",x,n);}}}else{printf("0\n");}}}
理解了Wythoff的规则这种题还是很水的
(三)尼姆博奕(Nimm Game):
- HDU组合游戏与博弈论入门小结(未完
- HDU组合游戏与博弈论入门小结(未完
- HDU5724(组合游戏,博弈论)
- [HDU 5795] A Simple Nim【博弈论&组合游戏】
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 博弈论入门小结
- 51nod-1185【博弈论】威佐夫游戏【未完】
- python添加django插件
- hdu 1385(最短路+输出路径)
- 错误记录--更改tomcat端口号方法,Several ports (8005, 8080, 8009)
- DOJ - 1002 Least Subsequence
- Node.js 学习笔记 —— console 控制台
- HDU组合游戏与博弈论入门小结(未完
- 线程的基本概念,状态,和状态之间的关系
- linux shell编程学习--test测试比较命令
- spring中lazy-init详解
- 101.[Leetcode]Symmetric Tree
- The Perfect Stall
- Fragment生命周期详解
- tomcat 基于apr配置https
- 线性表的顺序存储——顺序表