nim游戏
有N块石头和两个玩家A&B,A先将石头分成若干堆,然后按照BABA…..的顺序不断乱流取石头,能将剩下的石头一次取光的玩家获胜。每次去石头时,每个玩家只能从一堆石头中取走任意数目(大于0)的石头。
请问:玩家A有必胜的策略吗?设计程序输入每堆的石头个数,输出必胜策略。若没有必胜策略,也输出相应提示。
分析游戏本质,如果我能在留给对方一个各堆石头异或为0的结果,我就必胜。
算法一:算法一很简单,但是时间复杂度是石头的个数。列出所有取石头方案,计算他们是否相互异或为0.是则为最佳方案。
#include <stdio.h>
int XOR(int a[],int j)
{
int i,t;
t=a[0];
for(i=1;i<=j;i++)
{
t=a[i]^t;
}
return t;
}
int nim()
{
int i=0,j,k,n;
int t;
int a[100];
int *p;
p=a;
printf("input your stone and end by zero:");
while(scanf("%d",p+i)!=0&&a[i++]!=0);
j=i-2;
n=j;
for(;j>=0;j--)
{
t=a[j];
while(a[j]!=0)
{
a[j]--;
if(XOR(a,n)==0)
{
printf("the good plan is:");
for(k=0;k<=n;k++)
printf("%d ",a[k]);
printf("/n");
return 0;
}
}
a[j]=t;
}
printf("there is no good plan!/n");
return 0;
}
int main()
{
while(1)
nim();
}
算法二:算法二时间负责度为石头的堆数,效率更高。将各堆数目异或结果分别与各堆数目进行异或,如果该数比原数目小,则为最佳方案。
#include <stdio.h>
int XOR(int a[],int j) //求a数组内所有数相异或的结果
{
int i,t;
t=a[0];
for(i=1;i<=j;i++)
{
t=a[i]^t;
}
return t;
}
int nim()
{
int i=0,j,k,n;
int t;
int a[100];
int *p;
p=a;
printf("input your stone and end by zero:");
while(scanf("%d",p+i)!=0&&a[i++]!=0);
j=i-2;
n=j;
t=XOR(a,j);
if(t==0)
{
printf("there is no good plan!/n");
return 0;
}
else
for(n=0;n<=j;n++)
if((a[n]^t)<a[n])
{
a[n]=a[n]^t;
printf("the good plan is:/n");
for(i=0;i<=j;i++)
{
printf("%d ",a[i]);
}
printf("/n");
return 0;
}
else
continue;
printf("there is no good plan!/n");
return 0;
}
int main()
{
while(1)
nim();
}
哈哈,能够必胜的游戏,而且如果没有做过研究,根本看不出来必胜的规律,有意思~~