斐波那契博弈

斐波那契博弈

(本文为笔者的个人学习笔记,如有不当之处恳请各位读者指正)


问题描述:有一堆个数为n的石子,游戏双方轮流取石子,满足:

      (1)先手不能在第一次把所有的石子取完;

      (2)之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间(包含1和对手刚取的石子数的2倍)


解析:只需判断n是否为斐波那契数列中的数即可,若n为斐波那契数列中的数,则对于先手来说是必败局势。(注意前两项是1和2)。n为斐波那契数列中的数,

证明:当i=2时,先手只能取1个,后手取完剩余的1个,先手必败。

   假设当i<=k时结论成立。设先手取走y个,后手取走x个。

   则当i=k+1时,f(k+1)=f(k)+f(k-1),若先手第一次取的个数,则后手可以取走剩余的部分先手必败。

   若先手第一次取的个数,则这堆中剩余的石子<2y,后手可以取完,后手取走,又因为 所以。x最大达到  。 则对另一堆f(k):

              

                则

    所以,而所以,即。而此时先手可取的范围为    ,所以先手取不完剩余的那堆,先手必败。

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
	int fib[50];
	fib[0]=1;fib[1]=2;
	for(int i=2;i<45;i++){
		fib[i]=fib[i-1]+fib[i-2];//构造斐波那契数列
	}
	while(1){
		int n;
		cin>>n;
		if(n==0)
		    break;
		int i;
		for(i=0;i<45;i++){
		    if(fib[i]==n)//n是否为斐波那契数
			break;
		}
		if(i<45)
			cout<<"Second win"<<endl;//先手面临斐波那契堆,后手赢
		else
			cout<<"First win"<<endl;//先手面临的不是斐波那契堆,先手赢
	}
}
import java.util.*;
public class FibonaccisGame {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int fib[]=new int[50];
		fib[0]=1;fib[1]=2;
		for(int i=2;i<45;i++){
			fib[i]=fib[i-1]+fib[i-2];//构造斐波那契数列
		}
		while(true){
			int n=sc.nextInt();
			if(n==0)
				break;
			int i;
			for(i=0;i<45;i++){
				if(fib[i]==n)//判断n是否为斐波那契数
					break;
			}
			if(i<45)
				System.out.println("Second win");//先手面临斐波那契堆,后手赢
			else
				System.out.println("First win");//先手面临的不是斐波那契堆,先手赢
		}
	}

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值