为了账号安全,请及时绑定邮箱和手机立即绑定

博弈——Nim&SG函数函数(hdu1848)

标签:
算法

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1848


*如对Nim博弈不是很理解的请移步上篇博客http://blog.csdn.net/sm9sun/article/details/53229631


题目描述:


Fibonacci取石子

1、  这是一个二人游戏;
2、  一共有3堆石子,数量分别是m, n, p个;
3、  两人轮流走;
4、  每走一步可以选择任意一堆石子,然后取走f个;
5、  f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量);
6、  最先取光所有石子的人为胜者;

也就是说在Nim博弈的基础上,对取石子的个数加以限制。这里我们引入一个SG函数的概念

SG函数的百科说明:给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判负。

看起来有点抽象。实际上的意思就是 假如一个x,其f(x)=k,那么x的下一步操作,就是后继 可以满足0<=f(x->next)<k,当然其后继不可能等于k。


这就等同于Nim博弈里把k个石子变成0,1……k-1是一个道理

所以将这n枚棋子所在的顶点的SG值看作其n堆相应数量的石子,那么这个Nim游戏的每个必胜策略都对应于原来这n枚棋子的必胜策略

即又回到了Nim博弈


#include<stdio.h>int f[16]={1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597};//懒的写fib函数了= =!!! int SG[1005]={0};int E[1005];void f_sg(){int i,j;int h[20];E[0]=0;E[1]=1;for(i=2;i<=1000;i++){for(j=0;j<=15;j++){       	h[j]=0;	}for(j=0;f[j]<=i;j++) //SG值状态标记{h[E[i-f[j]]]=1;}for(j=0;j<=15;j++)if(h[j]==0)     //最小SG值 {E[i]=j;break;}}}int main(){int m,n,p,x;	f_sg();		while(~scanf("%d%d%d",&m,&n,&p),(m||n||p))	{			x=E[m]^E[n]^E[p];		if(x)			printf("Fibo\n");		else			printf("Nacci\n");	}	return 0;}





题目描述:先抛一个取石子问题:


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消