日历
网志分类
· 所有网志 (11)
· 水牛小屋 (4)
· 算法学习 (2)
· ACM/ICPC (3)
· 未分类 (2)
站内搜索
友情链接
· ZJU
· HDU
· PKU
· TC
· UVA
· SPOJ
· SGU
· URAL
· EL
· ProjectEuler
· Mathpuzzle
· CodeProject
· Algorithmist

订阅 RSS

0001524

歪酷博客

saintqdd

大家好,欢迎光临本博客(OIer,ACMer or coder,...)
mail: saintqdd@gmail.com  saintqdd@hotmail.com


« 上一篇: 搜索 下一篇: Range Minimum Query and Lowest Common Ancestor »
saintqdd @ 2008-03-04 15:10

       这两天学习一下新的知识---博弈论。发现我们生活中司空见惯的博弈游戏,竟然有如此完美的结论,根据这个结论能够知道某个人必输或必败,真的很神奇。其实我还没有真正的了解博弈,只是粗浅的了解了一下博弈论中的take-away game理论。游戏的规则很简单:
 
1):必须有两个人参与
2):游戏每次所能做出的合法的移动是有限的
3):必须是两个人控制同一个游戏对象,不能各个控制各自的。比如象棋,是一个人控制白的,一个人控制黑的,这现在不在研究范围。
4):双方必须轮流操控
5):当某个完家根据规则无路可走的时候就算失败了
6):游戏不管怎么完,都会在有限的步骤内结束,并定输赢
7):两个人每次都用最优的走法
 
下面举一个例子来形象的说明这个游戏的完法;
有一堆石子21个,双方轮流来拿走石子,每次可以的拿走的石子数是1,2,3,但是不可以不拿。现在从某一个人开始,那么若干步骤之内,必然会结果(赢家和输家)
现在我要立即回答,最后谁会赢呢,可能你不能一时答出,因为你觉得这个太随机了,谁输谁赢很难确定。神奇的理论告诉我们,最后的输赢不是取决与中间的过程,而是取决了谁先走和石子的个数。。
 
假如游戏的完家是I,II I先拿
我们从最后的结果出发讨论
 
0的话 I就输了,因为他没有可拿的了。
1,2,3 的话I就赢了,因为I可以一次把所有的石子都拿走,那么II就没拿的了。。
4的话 I就输了,因为I可以拿走 1,2,3个石子,那么会剩下3,2,1个石子,这样II可以一次拿走。。
 
5 6 7的话 I就又赢了,因为I可以那走1,2,3个石子,使剩下的石子为4,转上面的分析。。
8的话,I就输了,因为那走1,2,3剩下的就是5,6,7,所以是II赢了。。。
。。。
。。。
20的话 I就输了
21的话I就赢了
 
所以最终的结果是I赢了,看出没。不是随机的把,而是肯定的说是I赢。。。
 
当然还有个前提:就是 I知道每次拿多少是对自己最有利的,也不是随便拿的。。
 
下面我们将得出这个游戏模型的理论:
P点:就是P个石子的时候,对方拿可以赢
N点:就是N个石子的时候,自己拿可以赢;
通俗的解释就这样:
 
现在我们对上面的游戏进行PN分析;
0是P,因为对方拿0也就意味这他失败了
 
0
1
2
3
4
5 …..
P
N
N
N
P
N ……
 
通过对表格的研究,可以发现P,N点完全可以根据游戏规则和最种态计算出来。
 
比如这个游戏的最种点是0那么是P
现在关于P,N的求解有三个规则
(1):最终态都是P
(2):按照游戏规则,到达当前态的前态都是N的话,当前态是P
(3):按照游戏规则,到达当前态的前态至少有一个P的话,当前态是N
 
现在队上游戏重新计算,发现21点是N点,自己先肯定是赢
 
下面为了充分理解此结论,在举两个例子:
题目的意思是:在一个m*n的棋盘内,从(1,m)点出发,每次可以进行的移动是:左移一
,下移一,左下移一。然后kiki每次先走,判断kiki时候会赢(对方无路可走的时候)
 
谁输谁赢,现在只取决于棋盘的大小了。。
可以这样想像,我们从后往前推。假如是5*5的棋盘
*****
*****
*****
*****
*****
用数学坐标系,终态在(1,1),设为P
(1,1)->(1,2)->(2,1)->(2,2)->(1,3)->(2,3)->(3,1)->(3,2)->(3,3)…….
 p     N    N    N     P    …………
依次计算就 ok了,只要最后(m,n)是N则kiki赢。
测试用:
#include<iostream>
using namespace std;
bool map[2001][2001];//1 P 0 N;
int main(){
       int i,j,k;
       map[1][1]=1;
       for(i=2;i<=2000;i++){
              if(map[i-1][1])
                     map[i][1]=0;
              else map[i][1]=1;
              for(j=2;j<i;j++){
                     if(!map[i][j-1]&&!map[i-1][j-1]&&!map[i-1][j])
                            map[i][j]=1;
                     else map[i][j]=0;
              }
              if(map[1][i-1])
                     map[1][i]=0;
              else map[1][i]=1;
              for(j=2;j<i;j++){
                     if(!map[j-1][i]&&!map[j-1][i-1]&&!map[j][i-1])
                            map[j][i]=1;
                     else map[j][i]=0;
              }
              if(!map[i][i-1]&&!map[i-1][i-1]&&!map[i-1][i])
                     map[i][i]=1;
              else map[i][i]=0;
       }
       int M,N;
       for(i=1;i<=10;i++){
              for(j=1;j<=10;j++)
                     printf("%c ",map[i][j]?'P':'N');
              printf("\n");
       }
       while(scanf("%d%d",&M,&N)&&M&&N){
              if(map[M][N]) printf("What a pity!\n");
              else printf("Wonderful!\n");
       }
       return 0;
}
由于原题限制了内存,所以把pN输出找规律,发现只有m,n同时为奇的时候才输。。。。
 
另外一个例子是:
题目意思是说:两个人游戏,每次都是前一个人说出的数的基础上乘以一个(2。。。9)的数,谁先超过预先设定的值n,那么谁就赢了,基数是1
还有有个人先,胜败只取决与n的值.从后往前分析
举个例子:162
 
(无穷,162)->(162,18)->(17,9)->(8,1)
     p          N       p     N
(无穷,34012226)->( 34012225-3779137)->( 3779136-1889569)->( 1889568-209953)->
     p                N                   p                 N
 
(209952-104977)->( 104976-1220)->( 1219-610)->( 609-68)->( 67-39)->( 38-5)->(4,3)->(2,1)
      p              N            p         N        p       N     p    N
 
source code:
#include<iostream>
using namespace std;
int main(){
       __int64 N;
       bool f;
       while(scanf("%I64d",&N)!=-1){
              f=1;
              while(N!=1){
                     if(f){
                            N=N%9==0?N/9:(N/9+1);
                            f=0;
                     }
                     else{
                            N=N%2==0?N/2:(N/2+1);
                            f=1;
                     }
              }
              if(!f) printf("Stan wins.\n");
              else printf("Ollie wins.\n");
       }
       return 0;
}
 




评论 / 个人网页 / 扔小纸条
* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 


 

分类小组论坛
杂谈 , 娱乐、八卦 , 文学、艺术 , 体育 , 旅游、同城 , 象牙塔 , 情感 , 时尚、生活 , 星座 , 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定