zoukankan      html  css  js  c++  java
  • 威佐夫博弈

    什么是威佐夫博弈呢?

    我们用(x,y)表示当前两堆石子分别剩下x,y时的局势,(x,y)和(y,x)是同一种局势
    显然,当先手处于(0,0)的时候必败。我们将会使先手必败的局势叫做奇异局势。
    我们先用手推一下可以转移到先手(0,0)的局势。
    手推方法:人脑枚举最优策略易知(1,2)是奇异局势。画出平面直角坐标系,将所有的(1+k,2+k),(1+k,2),(1,2+k),(x,x),(2+k,1),(2,1+k),(2+k,1+k)((kin N_+))划掉,找到剩余的在y=x上面(x,y)最小的点(3,5),然后继续这么找
    通过长达咱也不知道多长时间的手玩数据可得到前几个奇异局势
    1:(1,2)
    2:(3,5)
    3:(4,7)
    4:(6,10)
    5:(8,13)
    6:(9,15)
    7:(11,18)
    更大的真的手玩不动了.jpg
    发现好像十分之有规律.jpg
    1.第i个奇异局势的x是之前所有奇异局势中,没有出现的最小非负整数。
    2.我们发现第i个奇异局势两个数的差是i.
    上面的规律在数据变大之后依旧成立吗?
    1.证明:
    如果不是没有出现的最小非负整数,则按照选的方法还可以选到更小的点作为第k个奇异局势
    2.证明:
    如果(x,x+k)不是奇异局势,则一定存在某种方法使对手面对奇异局势。
    1.取某一堆的石子:
    取少的那堆:变为(t,x+k),由于规律1正确,所以对手可以把局势变为第t个奇异局势,于是你没了与假设矛盾。
    取多的那堆:变为(x,t+k)。若t+k<x,则对手可以将局势转为t+k对应的奇异局势你又没了。若t+k>x,因为x<t+k<x+k,所以t+k可转化成某个奇异局势的y,对手就拿成了相应的奇异局势于是乎你又没了(可以手玩辅助理解)
    2.两堆都取:由于之前的奇异局势中,x与y的差都<k,所以无论如何你都不能把当前状态转移到一个奇异局势上去。而对手可以通过一些操作把非奇异局势转化为奇异局势。对手的玄学操作可以和1的情况差不多然后又输了
    我们知道这些性质之后,有什么用吗?
    每个奇异局势的x都是之前没有出现过的正整数中的最小值,不会与之前的数重合,而y=x+k,每个奇异局势的k都不同,导致y也不予之前的数重合。将所有奇异局势的x组成集合(A),所有的y组成集合(B)(这里默认x<y),发现(Aigcup B)=(N_+),(Aigcap B)=(emptyset)
    似乎这一点可以继续乱搞的样子。
    在这里介绍一个定理:(Beatty)定理:
    (a、b)是正无理数且 (frac{1}{a}) +(frac{1}{b})=1。记P={ [na] | n为任意的正整数},Q={ [nb] | n 为任意的正整数},([x]'指的是取x的整数部分)则P与Q是N+的一个划分,即P∩Q为空集且P∪Q为正整数集合N+。
    证明什么的当然是咕咕咕的
    证明走这里
    设第n个奇异局势的x表示为(an),那么第n个奇异局势的y表示为(an+n=(a+1)n)。因为第一个奇异局势是(1,2),所以(ageq 1)。按照(Beatty)定理,(frac{1}{a}+frac{1}{a+1}=1),即(a^2-a-1=0)。取大于1的根:(frac{1+sqrt5}{2})
    所以第n个奇异局势的第一个数就是(an=frac{1+sqrt5}{2})。若某个局势是奇异局势,则n为两数之差。当两数之差乘(frac{1+sqrt5}{2})是第一个数(即较小的数)时,它就是个奇异局势,先手必败,否则先手必胜。
    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<map>
    using namespace std;
    inline int read()
    {
    	char ch=getchar();
    	int x=0;bool f=0;
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')f=1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?-x:x;
    }
    int n,m;
    double ys=((sqrt(5.0)+1.0)/2.0);
    int main()
    {
    	n=read();m=read();
    	if(n<m) swap(n,m);
    	int cha=n-m;
    	if(m==(int)(ys*(double)cha)) printf("0");
    	else printf("1");
    }
    
  • 相关阅读:
    oracle11g安装客户端检查先决条件失败
    WinForm textbox 只允许输入数字
    Oracle存储过程
    Oracle游标
    Oracle之PL/SQL流程控制
    Oracle 变量
    log4net 使用
    Python Matplotlib 画图显示中文问题
    Oracle 数据迁移到 SQL Server
    C结构体【转】
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/11788178.html
Copyright © 2011-2022 走看看