首页
社区
课程
招聘
[旧帖] [分享]猴子选大王游戏牛叉解法 0.00雪花
发表于: 2012-5-19 12:50 1558

[旧帖] [分享]猴子选大王游戏牛叉解法 0.00雪花

2012-5-19 12:50
1558
在论坛闲逛的时候无意中看到的一个帖子,深受启发!不得不佩服人类的大脑,不得不相信大神的存在是可以秒杀一切的!到现在都不能理解他算法的原理,挺自卑的。看懂的朋友给我解释一下。

题目:帮猴子选大王
有N只猴子要选大王,选举规则如下:所有猴子按1,2,3……N编号围成一圈,从编号为1的猴子开始顺序1,2……m报数,凡报到m号的退出圈外,如此循环报数,直到圈内只剩一只猴子时,这只猴子就是大王。输入N,M得出猴王的编号。
       如输入:6,2;
          输出:5;

建议自己先尝试解看看,不然不会理解的那么深刻,或者觉得这个算法很平凡,很可能错过了一道很美的风景。

牛人是用php做的演示,我贴出他的源代码
<?php
        /*
        * @param $n 总数
        * @param $m 当报数到 m 时,m出列
        * @return 最后剩下的数字
        */

        function yuesefu($n,$m) {
        $r=0;
        for($i=2; $i<=$n; $i++) {
                $r=($r+$m)%$i;
        }
        return $r+1;
}
        print_r(yuesefu(6,2));//结果输出
?>

我用c++演示的代码:

#include <stdio.h>
/***********************************************
*函数名 : monkey
*函数功能描述 : 实现猴子选大王游戏结果
*函数参数 : n-猴子个数,m-选定的猴子编号
*函数返回值 : r+1 - 猴王的编号
*作者 :大熊
*函数创建日期 : 2012.5.19
**********************************************/

int monkey(int n,int m)
{
        int r=0,i=2;
        for(i=2; i<=n;i++)
        {
                r=(r+m)%i;
        }
        return r+1;
}
int main()
{
        int n = 0,m = 0;
        scanf("%d %d",&n,&m);//输入n,m的值
        printf("%d",monkey(n,m));//输出函数的返回值
        return 0;
}

不知道为什么会用这种方法,还在思考当中,等待牛人解释!

» 本文链接:http://php.oil58.com/?p=73
» 作者:大熊
» 转载请注明来源:编程学习

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
为了便于描述算法,这里将总人数设为n(编号0-(n-1),设从0开始报数),退出数字设为m,
报到x1=(m-1)的人退出,因为有可能m>n,所以把x1=(m-1)变形为x1=((m-1)mod n)。
当第一个人出列之后剩下的n-1个人组成了一个新的圆圈,编号从k1=(m mod n)开始,所有编号减去k1后,继续从0开始报数。
新的圆圈为0,1,2,3,……,n-3,n-2。
于是问题变成了(n-1)个人报数的子问题,同上退出的人的编号为x2=((m-1)mod (n-1)),所有编号减去k2=(m mod (n-1))
新的圆圈为0,1,2,3,……,n-4,n-3。
于是问题变成了(n-2)个人报数的子问题,同上退出的人的编号为x3=((m-1)mod(n-2)),所有编号减去k3=(m mod (n-3))
…………
直到最后剩下两个人,退出的人的编号x=(m-1)mod 2,则最后剩下的人的编号为K(n-1)=m mod 2
将K(n-1)还原为原数列的编号,K(n-1)= k1 + k2 + k3 + ……+K(n-1)
2012-12-2 12:45
0
游客
登录 | 注册 方可回帖
返回
//