取球游戏|2012年蓝桥杯B组题解析第十题-fishers

  1. (25')取球游戏

    今盒子里有n个小球,A、B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断。
    我们约定:
    每个人从盒子中取出的球的数目必须是:1,3,7或者8个。
    轮到某一方取球时不能弃权!
    A先取球,然后双方交替取球,直到取完。
    被迫拿到最后一个球的一方为负方(输方)
    请编程确定出在双方都不判断失误的情况下,对于特定的初始球数,A是否能赢?
    程序运行时,从标准输入获得数据,其格式如下:
    先是一个整数n(n<100),表示接下来有n个整数。然后是n个整数,每个占一行(整数<10000),表示初始球数。
    程序则输出n行,表示A的输赢情况(输为0,赢为1)。
    例如,用户输入:
    4
    1
    2
    10
    18

    则程序应该输出:
    0
    1
    1
    0

思路:零和博弈(只有输和赢,没有平局),博弈论,每个人都按最优策略出招。递归就能解决,但考虑到数据比较大,n<10000,随意要用记忆化递归来做,具体看代码。

代码:

#include<iostream>
using namespace std;

int a[1010];
//1和-1 

//记忆化递归 
bool f(int x){
	if(a[x] != 0){
		if(a[x] == 1){
			return true;
		}else{
			return false;
		}
	}
	int t = -1;
	if(x>1 && f(x-1) == false){
		t = 1;
	}
	if(x>3 && f(x-3) == false){
		t = 1;
	}
	if(x>7 && f(x-7) == false){
		t = 1;
	}
	if(x>8 && f(x-8) ==false){
		t = 1;
	}
	if(t == 1){
		a[x] = 1;
		return true;
	}else{
		a[x] = -1;
		return false;
	}
}

int main(){
	int n;
	cin>>n;
	int d;
	while(n--){
		cin>>d;
		if(f(d)){
			cout<<1<<endl;
		}else{
			cout<<0<<endl;
		}
	}
	return 0;
} 
原文地址:https://www.cnblogs.com/fisherss/p/10337414.html