取球问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33054265/article/details/51482820

有这么一个问题:
盒子里有n个球,A、B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个。
若每个人从盒中取出的球的数目必须是:1,3,7,8。轮到某一方取球时不能弃权,A先取球,然后双方交替取球,
规定最后取完球的人为胜方。假设两个都很聪明,每次都做出最有利于自己获胜的选择。
该题曾出现在某一年的蓝桥杯比赛上,不过我稍作了一些修改,如果想看蓝桥杯的原题,可以自行查询。

C代码如下:

#include <stdio.h>

int f(int n);

int f(int n){
    //还剩至少k(1、3、7、8)个球时,取1个后若发现已取完,则获胜
    //注意是先尝试取较多的,这样做能有效降低运行时间
    if((n>=8 && f(n-8)==0) || (n>=7 && f(n-7)==0) ||
    (n>=3 && f(n-3)==0) || (n>=1 && f(n-1)==0))
        return 1;

    return 0;
}

int main(){
    int n;

    printf(f(n) ? "A胜 " : "B胜 "); 

    return 0;
}

这种解决方法当球数n较大时运行时间会令人捉急,如果是算法类竞赛肯定行不通。
后来当输出较多数据时,会发现其结果有一定的规律:这里写图片描述
发现胜负结果有周期且为15,故我们可以将1-15个球的胜负结果保存至一个数组里,然后可以直接根据球数索引到数组值。
这是一个先暴力求出结果,然后找到规律,最后再优化代码的过程!
C代码如下:

#include <stdio.h>

int main(){
    int a[15] = {0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}, n;
    //a[0]-a[14]存放的是球数分别为15、1、2、3...14的胜负结果

    scanf("%d", &n);
    printf(a[n%15] ? "A胜\n" : "B胜\n");

    return 0;
}

文章若有不足之处,请大家多多指正!谢谢!

猜你喜欢

转载自blog.csdn.net/qq_33054265/article/details/51482820