zoukankan      html  css  js  c++  java
  • 博弈论模型总结

    博弈论五大模型

    前四大模型的深入理解

    Bash博弈模型

    一堆数量为n的石头,双方轮流每次从堆中取至少1个石头最多m个石头,谁先取完谁赢。

    设存在整数k和r使方程n=k*(m+1)+r成立,当r==0时先手必败,否则先手必赢。

    结论:n%(m+1) == 0, 先手必败

    Wythoff博弈模型

    两堆数量分别为x、y(x <= y)的石头,每次可以从一堆中取至少一个石头或者从两堆中取同等数量的石头,谁先取完谁赢。

    结论:x == floor( (sqrt(5)+1)/2 )*(y-x), 满足等式时先手必败

    Nim博弈模型

    任意m堆数量任意的石头,每次只能从一堆中获取至少1个石头,谁先取完谁赢

    设石头堆Di,Di的异或和k = D1D2...^Di,当且仅当k == 0时先手必败,否则先手必赢

    结论:D1D2...^Di == 0, 先手必败

    Fibonacci博弈模型

    一堆数量为n的石头,双方轮流从石头堆里取k[i]个石头(1≤k[i]≤2*k[i-1]),先取完的人获胜

    当且仅当n不是斐波那契数时,先手必胜,否则先手必败

    结论:Fib(n) == false, 先手必胜

    SG函数

    对sg函数的深入理解

    定义: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败。
    ______ N点:必胜点,处于此情况下,双方操作均正确的情况下必胜。
    定义:设mex{S}为集合S中第一个不存在的正整数
    定义:设sg(x)为x状态的sg值,sg(x)=mex{S},其中S为x的后继状态的sg值的集合
    当sg(x) == 0时, 没有获胜局面,此时处于P点
    性质:1、所有终结点的sg值都为0,即sg(0) == 0
    ______2、无论在N点如何操作,都至少存在一种情况进入P点
    ______3、无论如何,P节点的后继节点一定是N节点
    ______4、无论如何只能进入N点的点一定是P点

    例题:HDU 1848:Fibonacci again and again

    题解:假设只有一堆数量为n的石子

    定义sg(x)函数为当前石子数量的sg函数,每次只能取Fib[]数列的数

    sg[0] = 0, Fib[] = {1,2,3,5...}

    当x == 1时,可以取Fib[1]个石子,剩余0个石子,sg[1] = mex{sg[0]} = mex{0} = 1;

    当x == 2时,可以取Fib[2]、Fib[1]个石子,剩余1、0个石子sg[2] = mex{sg[1],sg[0]} = mex{0,1} = 2;

    当x == 3时,可以取Fib[3]、Fib[2]、Fib[1]个石子,剩余2、1、0个石子,sg[3] = mex{sg[2],sg[1],sg[0]} = mex{2,1,0} = 3;

    当x == 4时,可以取Fib[3]、Fib[2]、Fib[1]个石子,剩余3、2、1个石子,sg[4] = mex{sg[3],sg[2],sg[1]} = mex{3,2,1} = 0;

    ......

    当x == n时,若sg[n] != 0,先手必胜

    对于多堆石子,类比Nim游戏:

    sg[n]sg[m]sg[k] == 0, 先手必败

    #include<iostream>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<string.h>
    #include<queue>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define rep(i, a, b) for(int i=(a); i<(b); i++)
    #define sz(a) (int)a.size()
    #define de(a) cout<<#a<<" = "<<a<<endl
    #define dd(a) cout<<#a<<" = "<<a<<" "
    #define be begin
    #define en end
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef vector<int> vi;
    const int N = 1005;
    vi f;
    void fib(){
    	f.pb(1), f.pb(1);
    	for(int i = 1;f[i] < N;i++){
    		f.pb(f[i]+f[i-1]);
    	}
    	f.erase(f.begin());
    }
    int sg[N];
    void SG(){
    	vi::iterator it;
    	sg[0] = 0;
    	for(int i = 1;i < N;i++){
    		set<int> q;
    		for(it = f.begin();it != f.end() && *it <= i;it++){
    			q.insert( sg[i-(*it)] );
    		}
    		set<int>::iterator sit = q.begin();
    		int t = 0;
    		for(;sit != q.end();sit++){
    			if(t < *sit) {
    				break;
    			}
    			else
    				t = *sit+1;
    		}
    		sg[i] = t;
    	}
    }
    int main()
    {
    	std::ios::sync_with_stdio(false);
        std::cin.tie(0);
    	fib();
    	SG();
    	int m,n,p;
    	while(cin >> m >> n >> p){
    		if(m == 0) break;
    		if((sg[m]^sg[n]^sg[p]) == 0) cout << "Nacci" << endl;
    		else cout << "Fibo" << endl;
    	}
    	return 0;
    }
  • 相关阅读:
    NPOI导出excel表格应用
    通过用户密码获取共享文件
    sql之left join、right join、inner join的区别
    C#日志编写
    C#预编译指令
    匿名类型(C# 编程指南)
    反射
    SQL通用查询
    Lambda 表达式(C# 编程指南)
    自定义用户控件编写——(文件夹目录选择)
  • 原文地址:https://www.cnblogs.com/Ace-Monster/p/9415889.html
Copyright © 2011-2022 走看看