博弈问题

博弈问题概述    

        常见的博弈类问题有三种:巴什博弈、威佐夫博弈和尼姆博弈。

        一般的思路都是寻找奇异局势(必败态)。

        必败态:下一步无论如何处理都会达到必胜态;

        必胜态:下一步至少存在一种处理可以达到必败态。

        如果一开始是一个奇异局势,则先手必败;否则,先手必赢(如果双方都懂得游戏规则)。

巴什博弈

问题描述

        最简单的一类博弈问题。只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个。最后取光者得胜。

解决思路

        显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。

        因此我们发现了如何取胜的法则:

        如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。

例子

HDU 1846
#include <stdio.h>

int main()
{
    int C;
    int n, m;
    scanf("%d", &C);
    while (C --)
    {
        scanf("%d%d", &n, &m);
        if (n%(m+1) == 0)
            printf("second\n");
        else
            printf("first\n");
    }
    return 0;
}

HDU 1847
        只要保证剩下的数量为3的倍数,即可确保胜利。因为留下3的倍数时,对手有两种情况:
        1):如果轮到对方抓牌时只剩3张牌,对方要么取1张,要么取2张,剩下的你全取走,win! 
        2):如果轮到对方抓牌时还剩3*k张牌,对手不管取多少,剩下的牌数是3*x+1或者3*x+2。轮到你时,你又可以构造一个3的倍数。 所以无论哪种情况,当你留给对手为3*k的时候,你是必胜的。
#include <stdio.h>

int main()
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        if (n%3 == 0)
            printf("Cici\n");
        else
            printf("Kiki\n");
    }
    return 0;
}

威佐夫博弈

问题描述

        威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

解决思路

        解决思路同样是寻找奇异局势。
        

        用(ak, bk)(ak ≤ bk ,k=0, 1, 2, ... , n)表示两堆物品的数量并称其为局势。很显然,(0, 0)是一个奇异局势。前几个奇异局势是:(0, 0)、(1, 2)、(3, 5)、(4, 7)、(6, 10)、(8, 13)、(9, 15)、(11, 18)、(12, 20)。

        可以看出,a0=b0=0,ak是未在前面出现过的最小自然数,而 bk= ak + k。

        关于奇异局势的几个性质:

        (1):任何自然数都包含在一个且仅有一个奇异局势中;

        (2):任意操作都可将奇异局势变为非奇异局势;

        (3):采用适当的方法,可以将非奇异局势变为奇异局势。

例子

尼姆博弈

问题描述

        有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

解决思路

        用一个三元组(a, b, c)表示局势。 任何奇异局势 (a, b, c)都有a ^ b ^ c = 0。
        如果我们面对的是一个非奇异局势(a,b,c),要如何变为奇异局势呢?
        假设 a < b < c,我们只要将 c 变为 a ^ b,即可,因为有如下的运算结果:a ^ b ^ (a ^ b)=(a ^ a) ^ (b ^ b)=0 ^ 0=0。要将c 变为a ^ b,只要从 c中减去 c - (a ^ b)即可。

例子

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用差分进化算法求解四方演化博弈问题的 MATLAB 代码示例: ```matlab % 定义博弈矩阵 payoff_matrix = [1, 3, 0, 5; 0, 2, 4, 1; 3, 1, 2, 0; 2, 4, 1, 3]; % 定义差分进化算法参数 pop_size = 50; % 种群大小 max_generations = 100; % 最大迭代次数 F = 0.5; % 缩放因子 CR = 0.9; % 交叉概率 % 初始化种群 population = rand(pop_size, 4); % 每个个体有四个策略值,取值范围[0,1] % 迭代优化 for generation = 1:max_generations % 计算适应度函数值 fitness = zeros(pop_size, 1); for i = 1:pop_size fitness(i) = calculate_fitness(population(i, :), payoff_matrix); end % 更新种群 new_population = zeros(pop_size, 4); for i = 1:pop_size % 随机选择三个不同的个体作为参考向量 idx = randperm(pop_size, 3); x1 = population(idx(1), :); x2 = population(idx(2), :); x3 = population(idx(3), :); % 变异操作 mutant = x1 + F * (x2 - x3); % 交叉操作 trial = crossover(mutant, population(i, :), CR); % 选择操作 if calculate_fitness(trial, payoff_matrix) >= fitness(i) new_population(i, :) = trial; else new_population(i, :) = population(i, :); end end population = new_population; end % 计算最优策略 best_strategy = population(1, :); best_fitness = calculate_fitness(best_strategy, payoff_matrix); % 打印结果 disp('最优策略:'); disp(best_strategy); disp('最优适应度:'); disp(best_fitness); % 定义适应度计算函数 function fitness = calculate_fitness(strategy, payoff_matrix) fitness = strategy * payoff_matrix * strategy'; end % 定义交叉操作函数 function trial = crossover(mutant, target, CR) mask = rand(size(mutant)) < CR; trial = target .* mask + mutant .* (1 - mask); end ``` 请注意,这只是一个简单的示例代码,实际应用中可能需要根据具体问题进行调整和扩展。同时,你可以根据需要修改博弈矩阵和算法参数来进行实验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值