博弈论

【转】今天看了关于博弈论的一些东西,大概明白了一些,但是也说不出个所以然来。主要就是要分析必胜和必败的局面,对于我来说理解起来比较费劲。这里就只能知道这么一回事,还需要在以后的做题中慢慢理解。现在就以两道简单题来做一下,领悟一下。

第一道是poj1067,结题报告是从别人那里转载来的:

题目描述:

取石子游戏

Description

有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。

Input

输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,000。

Output

输出对应也有若干行,每行包含一个数字1或0,如果最后你是胜者,则为1,反之,则为0。

Sample Input

2 1
8 4
4 7

Sample Output

0
1
0
解题报告:
 
 
有两堆石子,给定两堆石子的数量,可以进行如下两种操作:
1、从某一堆中拿走一定数量的石子
2、从两堆石子中拿走相同数量的石子
两个人轮流拿,假设都按照最优策略来操作,谁输呢?
 
问题类型:威佐夫博弈
 
分析:当某一个人面对(0,0)的局势时,必败,我们把面临该局势必败的局势称为必败局势。易知上一个必败局势为(1,2),因为不管面临该局势的人采用何种操作,下一个人都可以使之面临(0,0)的趋势,则接下去的必败局势分别为(3,5),(4,7),(5,9)......
 
设第k+1个必败局势为(ak,bk),ak<=bk,有如下性质:
 
ak=(sqrt(5)+1)*k/2;bk=ak+k;
 
我们称不满足该条件的局势称为必胜局势,因为总可以进行一次操作使得下一个人面临必败局势。
 
下面我们要做的工作就是判断该局势(a,b)是不是必败局势。
我们首先要估算k;假设k是必败局势,k=(sqrt(5)-1)*a/2;
对k取整,如果a=(sqrt(5)+1)*k/2不成立,我们可以对k进行修正:k++;
此时, 若b=a+k则该局势为必败局势。

代码实现:

<span style="font-size:18px;">#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;

int main()
{
    int a, b, k;
    double r = (sqrt(5.0)+1)/2.0;
    while(~scanf("%d%d", &a, &b)){
        if(a>b)
            swap(a,b);
        k = b - a;
        if(a != int(r*k))
            printf("1\n");
        else printf("0\n");
    }
    return 0;
}
</span>
第二题是暑假第二次比赛的一道题:
题目描述:


  Box Game 

There are two identical boxes. One of them contains n balls, while the other box contains one ball. Alice and Bob invented a game with the boxes and balls, which is played as follows:

Alice and Bob moves alternatively, Alice moves first. For each move, the player finds out the box having fewer number of balls inside, and empties that box (the balls inside will be removed forever), and redistribute the balls in the other box. After the redistribution, each box should contain at least one ball. If a player cannot perform a valid move, he loses. A typical game is shown below:

\epsfbox{p12293.eps}

When both boxes contain only one ball, Bob cannot do anything more, so Alice wins.

Question: if Alice and Bob are both clever enough, who will win? Suppose both of them are very smart and always follows a perfect strategy.

Input 

There will be at most 300 test cases. Each test case contains an integer n ( 2$ \le$n$ \le$109) in a single line. The input terminates by n = 0.

Output 

For each test case, print a single line, the name of the winner.

Sample Input 

2
3
4
0

Sample Output 

Alice
Bob
Alice

解题思路:通过观察我们可以发现,Bob想要赢,也就是打印出Bob的名字时,输入的数字是3、7、15、31......也就是2^n-1.所以我们只需要在这些数字打印出Bob就行。我写了一份代码,也在网上看到一份代码,思路的是一样的,但是可以从中学到一点技巧,也就是n&(n-1)的用法。先贴我的代码,在贴一份别人的代码。
实现代码:
#include<cstdio>
int main()
{
    int n;
    while(~scanf("%d", &n)){
        if(n==0) break;
        int sum = 1;
        int flag = 0;
        for(int i = 0; i<100; i++){
            sum *= 2;
            if(n == sum-1)
            {
                flag = 1;
                break;
            }
        }
        if(flag) printf("Bob\n");
        else printf("Alice\n");
    }
    return 0;
}

别人的代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include<math.h>
#include<cstdlib>
using namespace std;
#include<stdio.h>
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n==0) break;
        ++ n;
        if((n & (n - 1)))
            printf("Alice\n");
        else
            printf("Bob\n");
    }
    return 0;
}
顺带学习n&(n-1)的一种用法:
n&(n-1)作用:将n的二进制表示中的最低位为1的改为0,先看一个简单的例子:
n = 10100(二进制),则(n-1) = 10011 ==》n&(n-1) = 10000
可以看到原本最低位为1的那位变为0。
可以判断一个数是否是2的方幂
n > 0 && ((n & (n - 1)) == 0 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值