数学专题---博弈论【更新中】

来源:互联网 发布:js确定取消对话框 编辑:程序博客网 时间:2024/06/04 20:06

1.从nim游戏讲博弈论
考虑这样一个游戏,有三堆火柴,记为(a,b,c),每次可以在一堆中取任意根,也可以都拿走,但不能从多个堆中同时拿,无火柴可拿的人输.
我们可以推导出sg函数,SG(x)=x,根据SG定理,x1^x2^…..^xn=0则一定输
那么当游戏不是nim游戏的时候,如何确定胜负关系呢


例题1. hdu153
原题
题意:跟nim游戏一样,但不可以取任意根,只能取k根火柴,k属于集合限定集合s。
题解:因为数据范围很小,递推求SG函数,找到最小的不能达到的状态
再取亦或。
代码:

int T,k,i,n,m,j,x,y,z,ans;int s[10005];int d[105];int get(int x){ int mm[105]; int i; if (s[x]!=-1) return s[x]; if (x<d[1]) return s[x]=0; Fill(mm,0); FOR(i,k) {   if(d[i]>x) break;   mm[get(x-d[i])]=1; }  REP(i,0,10005) {if (mm[i]==0) {return s[x]=i;}}}int main(){  offcin;  while(cin>>k&&k){   FOR(i,k) cin>>d[i];   sort(d+1,d+k+1);   Fill(s,-1);   cin>>T;   get(4);   FOR(j,T)   {    cin>>n;    ans=0;    fori {cin>>x; ans^=get(x);}    if(ans==0) cout<<"L"; else cout<<"W";   }    cout<<endl;  }}

hdu1079
原题
题意:给一个日期,每次加一个月或者一年,不能出现不存在的日期
日期超过2001,11,4的人输
题解:简单的博弈,从必败状态开始搜,标记,写起来好像比较烦…不写了

还有巧妙的做法:
找规律,不然是月份加一,还是日期加一,都改变了奇偶性,只有两个特殊日期9月30日,和11月30日例外。
那么目标日期是11月4日,为奇数。初始日期如果为偶数的话,先者必胜。
考虑特殊是日期,两个特殊日期本来为奇数,移动一步还是奇数。那么会不会在中途经过这两个日期呢。
如果本来为偶数,如果经过特殊日期就会改变奇偶,从必胜到必败。作为先手,不会主动进入特殊日期,而后者不可能从奇数依旧到达特殊日期的奇数。
如果本来为奇数,同样先手想赢,但是不可能进入特殊日期。保持奇偶性交替变化。
这样一来只可能是初始为特殊日期,否则中途不可能出现特殊日期


HDU1847
原题
题意:n张牌,两个人,每次只能抽2的倍数张
题解:打个表就能发现,三的倍数后手赢不然先手赢


HDU2516
原题
题意:n个石子,取走最后一块的赢,每一次不能超过前一次的两倍,第一次不能都拿走
题解:著名的斐波那契FIB博弈,证明

0 0