概述
斐波那契博弈
简介
一堆有 n n n个物品,如果有甲乙两个人。甲和乙轮流从这对物品中选取物品,第一次可以取 1 ∼ n − 1 1sim n-1 1∼n−1个物品,后一个人能取的物品数范围是 1 1 1到前一个人取的物品数 2 2 2倍,最后取光物品的人获胜。
思路
若甲先手,设当前物品数为 r r r。
当 r ≤ 3 rle 3 r≤3时,甲无法取胜,甲必败。
当 r = 4 r=4 r=4时,甲取 1 1 1,乙剩 3 3 3个无法取胜,故甲必胜。
当 r = 5 r=5 r=5时,甲若取 2 2 2个及以上乙必胜。甲若取 1 1 1个,乙取 1 1 1个又变成了 r = 3 r=3 r=3的情况,乙胜。
根据上述过程,不难发现要想自己赢必须尽可能保证对方拿到斐波那契数。
也就是说,甲先手获胜需要满足 n n n不是斐波那契数。
算法模板
首先我们需要能计算斐波那契数
- 递归法
long long fib(int k){
if(k<=1) return 1;
else return fib(k-1)+fib(k-2);
}
- 递推法
long long fib(int k){
fib[0]=fib[1]=1;
for(int i=2;i<=k;i++){
fib[i]=fib[i-1]+fib[i-2];
}
return fib[k];
}
模板
由于递推法的线性复杂度,所以采取递推来实现斐波那契博弈。
bool fibG(int n){//这里返回的是先手玩家是否可以获胜
fib[0]=fib[1]=1;
for(int i=2;fib[i-2]<=n;i++){
if(fib[i-2]==n) return false;
fib[i]=fib[i-1]+fib[i-2];
}
return true;
}
例题
hdu2516
大概概括一下,就是 n n n表示物品数,输出第一个人先手时哪个人能获胜,输出获胜的人(First win or Second win),输入 0 0 0表示结束。
#include <iostream>
using namespace std;
int fib[1001];
bool fibG(int n){//这里返回的是先手玩家是否可以获胜
fib[0]=fib[1]=1;
for(int i=2;fib[i-2]<=n;i++){
if(fib[i-2]==n) return false;
fib[i]=fib[i-1]+fib[i-2];
}
return true;
}
int main(){
int n;
while(cin>>n,n!=0){
if(fibG(n)) cout<<"First winn";
else cout<<"Second winn";
}
return 0;
}
尝试推广
如果规定先取完的人输,再看一下策略。
因为甲可以取 1 ∼ n − 1 1sim n-1 1∼n−1个,那么甲直接取 n − 1 n-1 n−1个,留下 1 1 1个给乙,则乙必输。
最后
以上就是纯情眼睛为你收集整理的【博弈论】斐波那契博弈斐波那契博弈例题尝试推广的全部内容,希望文章能够帮你解决【博弈论】斐波那契博弈斐波那契博弈例题尝试推广所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复