约瑟夫问题:M个人围成一圈,从第一个人开始依次从1到N循环报数,每当报数为N时此人出圈,直到剩一人为止

请按退出次序输出出圈人原来的编号以及留在圈中的最后一个人原来的编号。请用TC编程,非常感谢!

此题可用数学方法求解。


设有n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数    (用数学方法解的时候需要注意应当从0开始编号,因为取余会取到0解。)


实质是一个递推,n个人中最终留下来的序号与n-1个人中留下来的人的序号有一个递推关系式。


假设除去第k个人,则


0, 1, 2, 3, ..., k-2, k-1, k, ..., n-1          // 原始序列 (1)


0, 1, 2, 3, ..., k-2,      , k, ..., n-1        // 除去第k人,即除去序号为k-1的人   (2)


k, k+1, ..., n-1,    0,    1,        ..., k-2  // 以序号k为起始,从k开始报0  (3)


0, 1,     ..., n-k-1, n-k, n-k+1, ..., n-2   // 作编号转换,此时队列为n-1人  (4)


变换后就完完全全成为了(n-1)个人报数的子问题,注意(1)式和(4)式,是同一个问题,不同的仅仅是人数。比较(4)和(3),不难看出,0+k=k, 1+k=k+1, ... ,(3)式中'0'后面的数字,((n-3)+k)%n=k-3,((n-2)+k)%n=k-2, 对于(3)式中'0'前面的数字,由于比n小,也可看作(0+k)%n=k,  (1+k)%n=k+1,  故可得出规律:


设(3)中某一数为x' , (4)中对应的数为x,则有:x'=(x+k)%n.


设x为最终留下的人序号时,队列只剩下1人时,显然x=0; 此时可向前回溯至2人时x对应的序号,3人时x对应的序号……直至n人时x的序号,即为所求。


递归法表示如下:

#include <stdio.h>
int main()
{
    int M,N,s=0;
    scanf("%d%d",&M,&N);
    for (int i=2;i<=M;++i)
        s=(s+N)%i;
    printf("%d\n",s+1);
    return 0;
}

温馨提示:内容为网友见解,仅供参考
第1个回答  2011-04-20
#include "stdio.h"
#define M 65

int main()
{
int i,k,n,m,count;
int name[M];
scanf ("%d %d",&n,&m);// 有n个人
for (i = 0;i < n;i ++)//编号
{
name[i]= i +1;
}
k = 0;
for (i = 0;i < n;i ++)
{
count = 0;
while (count < m) //每到m个人就输入
{
while (name[k] == 0)
k = (k + 1)%n;
count ++;
k = (k + 1)%n;
}
k --;
if (k < 0)
k = n-1;
printf ("%d\n",name[k]);
name[k] = 0;
}
return 0;
}
如果哪里不明白,就提出来啊本回答被提问者采纳
第2个回答  2011-04-20
#include <stdio.h>
#include<stdlib.h>
int main()
{
int n, m, i, s = 0;
printf ("M N = ");
scanf("%d%d", &m, &n);
for (i = 2; i <= m; i++)
{
s = (s + n) % i;
}
printf ("\nThe winner is %d\n", s+1);
return 1;
}

约瑟夫问题:M个人围成一圈,从第一个人开始依次从1到N循环报数,每当报数...
设有n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数 (用数学方法解的时候需要注意应当从0开始编号,因为取余会取到0解。)实质是一个递推,n个人中最终留下来的序号与n-1个人中留下来的人的序号有一个递推关系式。假设除去第k个人,则 0, 1, 2, 3...

【pascal】求约瑟夫问题的递归求法(程序)
约瑟夫问题。M个人围成一圈,从第一个人开始报数,数到n的人出圈。再由下一个人开始报数,数到n的人出圈,……输出依次出圈人的编号。M值预先选定,n值由键盘输入。[解题分析]用一个数组存储M个人,先初始化数组,并使数组元素的值等于1,输入n的值。从1到M循环,判断该元素是否为数到n的元素,...

JOSEPHUS 好人 求算法思路,最好有代码
从第一个人开始对还未扔下海的人进行计数,每数到9时,将结构中的标记改为0,表示该人已被扔下海了。这样循环计数直到有15个人被扔下海为止。一般形式约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的人的序号为5,4,6,...

约瑟夫问题的猴子选王
一. 问题描述:一堆猴子都有编号,编号是1,2,3 ...m,这群猴子(m个)按照1-m的顺序围坐一圈,从第1开始数,每数到第N个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。约瑟夫密码问题问题描述:编号为1、2、3、...、N的N个人按顺时针方向围坐一...

约瑟夫问题的问题来历
这里给出一种实现方法。题目中30个人围成一圈,因而启发我们用一个循环的链来表示,可以使用结构数组来构成一个循环链。结构中有两个成员,其一为指向下一个人的指针,以构成环形的链;其二为该人是否被扔下海的标记,为1表示还在船上。从第一个人开始对还未扔下海的人进行计数,每数到9时,将结构...

1~M个人,围成一个圈,轮流报数,报到S的人出列,按顺序输出出列的人的编 ...
必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依 次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止 \/ include<iostream> using namespace std;void main() { int i, j, k = 1, a[31]; \/\/ M = 30 for(i...

猴子选大王是哪一类的题目??快!!!
实际是Josephus(约瑟夫)问题 [问题描述]M只猴子要选大王,选举办法如下:所有猴子按1…M编号围坐一圈,从第1号开始按顺序1,2,…,N报数,凡报到N的猴子退出到圈外,如此循环报数,直到圈内只剩下一只猴子时,这只猴子就是大王。M和N由键盘输入,打印出最后剩下的那只猴子的编号。[问题分析]这个...

利用C++解决约瑟夫问题。
这里补充一下约瑟夫问题的描述:N个人围成一圈,从第一个开始报数,数到M的人出队,然后他的下一位继续从1开始报数,数到M的出队,如此循环直到剩下一个人,求最后剩下的那个人最初是队伍中的第几位。解决这道题可以采用模拟报数的方法,建立一个大小为N的数组,数组的第N个元素表示第N个人是否...

关于约瑟夫环问题的实验报告书中详细设计
1.需求分析和说明 分析约瑟夫问题:n个人围成圈,每人各持一个密码,任选一个正整数作为报数上限值m,从第一个人开始,数到第m个人,删除并以出列者密码作为新的m值,从下一个人开始进行第二轮操作,直到所有人都出列。例如n=6, m=3, 处理过程下图。2.设计 n个人围圈,形成线性关系;处理为...

什么是约瑟夫问题
约瑟夫问题是一个著名的问题:假设有N个人围坐在一圈,从第一个人开始报数,每报数到第M个人时,那个人就会被淘汰,最终只剩下一个人,其余的人都会被淘汰。例如,如果N=6且M=5,那么被淘汰的人的编号将是5、4、6、2、3。最后,编号为1的人将留下。假设在圈子里的前K个人是好人,后K个人...

相似回答