第二届蓝桥杯省赛---取球游戏

取球游戏

今盒子里有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

思路一:零和博弈,每个人都按照最优策略出牌,递归就可以解决,但是数据比较大,采用记忆化递归

f(局面 x) ---> 胜负   

边界条件处理 

for(对我所有可能的走法)

     试着走一步 -----> 局面y 

      胜负 t = f(y);    

   if(t==负) return 胜    局面  

  return 负 

}

也就是说,让A尝试他走哪一步不会输,他走出一步后,局面发生改变,由对手去下剩下的局面,通过对手的输赢来判断自己的输赢。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 1e4+10;
 8 int a[maxn];/*a的记忆化体系建立起来之后只有1,-1*/
 9 
10 //记忆化递归
11 bool f(int x){
12     /*递归边界*/
13     if(x==0) return true;
14     if(a[x]!=0){
15         if(a[x]==1) return true; 
16         else{
17             return false;
18         }
19     }
20     int flag = 0;
21     /*  对A来说,如果球数大于1,可以先尝试去拿一个,
22         如果对方取一个之后对方输了,说明A赢了返回true,
23         接下来类似,,博弈论。。。
24     */
25     if(x>1&&f(x-1)==false) flag=1;
26     if(x>3&&f(x-3)==false) flag=1;
27     if(x>7&&f(x-7)==false) flag=1;
28     if(x>8&&f(x-8)==false) flag=1;
29 
30     if(flag){
31         a[x]=1;
32         return true;
33     }
34     else{
35         a[x]=-1;
36         return false;
37     }
38 }
39 
40 int main(){
41     int n;
42     cin>>n;
43     while(n--){
44         int d;
45         cin>>d;
46         if(f(d)){
47             cout<<1<<endl;
48         }
49         else{
50             cout<<0<<endl;
51         }
52     }
53 
54     return 0;
55 }

 思路二:由于题目的要求,两个人取球,其中每人每一次必取 1, 3, 7, 8 其中的一个数量的球,并且最后一个球被取到的人输,因此得出以下表格:

因此对于A君先取球,判断A君的游戏情况,可以把“我先拿胜利”的情况均存在r[]数组中并赋值为1,否则r[]数组中其他值赋值为0,即可。

表格的具体构造过程如下:初始值:int a[maxn]={-1,0,1,0,1,0,1,0,1};       -1表示0个球的情况不存在,存了8个球进去了下标从0开始的

然后 i = 9;判断 ( a[i-8]==1&& a[i-3]==1&& a[i-7]==1 && a[i-1]==1 ),
如果成立,说明无论A走哪一步,对方都可以胜利,则a[i] = 0,否则,a[i]=1;

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 const int maxn = 1e4+10;
 6 int a[maxn];
 7 void init(int a[]){
 8     a[0] = -1;
 9     for( int i=2; i<=8; i+=2){
10         a[i]=1;
11     }
12     for( int i=9; i<=maxn; i++ ){
13         if(a[i-1]==1&&a[i-3]==1&&a[i-7]==1&&a[i-8]==1){//无论A走哪一步,都是对方赢,则a[i]=0,即i个球A先拿时,A必输
14             a[i]=0;
15         }
16         else{
17             a[i]=1;
18         }
19     }
20 }
21 
22 int main(){
23     init(a);
24     int n;
25     cin>>n;
26     while(n--){
27         int d;
28         cin>>d;
29         if(a[d]){
30             cout<<1<<endl;
31         }
32         else{
33             cout<<0<<endl;
34         }
35     }
36     return 0;
37 }

猜你喜欢

转载自www.cnblogs.com/Bravewtz/p/10424642.html