取球游戏
今盒子里有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 }