计算机三级考试约瑟夫环出圈求解释 wait on line!

有n个人从1到n编号坐一圈,从第s个进行1到m报数,报到m这个人出圈,从他下一个再1到m报数,如此下去,所有人都 出圈,现在编个子程序实现此功能

我有答案,但是看得迷迷糊糊的,求大侠帮我解释解释吧,我才刚学c语言,务必讲得要通俗易懂,徒儿谢谢老师们
void mm(void)
{int i,j,k,s1,w;
s1=s;
for(i=1;i<=n;i++)
p[i-1]=i;
for(i=n;i>=2;i--) \*下面想不明白,请说说每句都是干什么用的\
{ s1=(s1+m-1)%i; \* ?\
if(s1==0)
s1=i;
w=p[s1-1];
for(j=s1;j<=i-1;j++)
p[j-1]=p[j];
p[i-1]=w;
}
}

这个我第一次考的时候也考了,结果没有过,而第二次考就考了个很简单的。但是这个题目我也会了。现在已经过去两年了,忘了。但是给你个建议就是:

你可以自己在TUBRO C程序上运行,然后看每步的结果那样就很容易看懂了。下面是我自己做过的你看看思路:
★☆题目57(无忧id 109 出圈题)
设有n个人围坐一圈并按顺时针方向从1到n编号,从第s个人开始进行1到m的报数,报数到第m个人,此人出圈,再从他的下一个人重新开始1到m的报数,如此进行下去直到所有的人都出圈为止。现要求按出圈次序,每10人一组,给出这n个人的顺序表。请考生编制函数Josegh()实现此功能并调用函数WriteDat()把结果p输出
到文件JOSE.OUT中。
设 n = 100, s = 1,m = 10。
(1) 将1到n个人的序号存入一维数组p中;
(2) 若第i个人报数后出圈,则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置;
(3) 重复第(2)步直至圈中只剩下p[1]为止。
注意:部分源程序存放在文件prog1.c中。
请勿改动主函数main()和输出数据函数WriteDat()的内容。
#include <stdio.h>
#define N 100
#define S 1
#define M 10

int p[100], n, s, m ;
void WriteDat(void) ;

void Josegh(void)
{ int i,j,s1,w;
s1=s;
for(i=1; i<=n; i++)
p[i-1]=i;
for(i=n; i>=2; i--)
{ s1=(s1+m-1)%i;
if(s1==0) s1=i;
w=p[s1-1];
for(j=s1; j<i; j++)
p[j-1]=p[j];
p[i-1]=w;
}
}

void main()
{
m = M ;
n = N ;
s = S ;
Josegh() ;
WriteDat() ;
}

void WriteDat(void)
{
int i ;
FILE *fp ;

fp = fopen("jose.out", "w") ;
for(i = N - 1 ; i >= 0 ; i--) {
printf("%4d ", p[i]) ;
fprintf(fp, "%4d", p[i]) ;
if(i % 10 == 0) {
printf("\n") ;
fprintf(fp, "\n") ;
}
}
fclose(fp) ;
}

此题的另一种形式(实际上机的考试题)如下
设有n个人围坐一圈并按顺时针方向从1到n编号,从第s个人开始进行1到m的报数, 报数到第m个人, 此人出圈, 再从他的下一个人重新开始1到m的报数,如此进行下去直到所有的人都出圈为止。现要求按出圈次序,给出这n个人的顺序表p。请考生编制函数Josegh()实现此功能并调用函数WriteDat()把编号按照出圈的顺序输出到OUT.DAT文件中。
注意:第1个出圈的编号存放在p[0]中,第2个出圈的编号存放在p[1]中,直至第n个出圈的编号存放在p[n-1]中。
设 n = 100, s = 1, m = 10进行编程。
注意: 部分源程序存放在PROG1.C中。
请勿改动主函数main()和输出数据函数WriteDat()的内容。
#include <stdio.h>
#define N 100
#define S 1
#define M 10
int p[100], n, s, m ;
void WriteDat(void) ;
void Josegh(void)
{ int i,j,s1,w,q[100];
for(i=0;i<n;i++) q[i]=0;
s1=s;
for(i=1; i<=n; i++) p[i-1]=i;
for(i=n; i>=2; i--)
{ s1=(s1+m-1)%i;
if(s1==0) s1=i;
w=p[s1-1];
for(j=s1; j<i; j++) p[j-1]=p[j];
p[i-1]=w;
}
/*由于上面的解法是倒着存放出圈数,以下采用两个循环的是将数组p中的数据倒过来以实现题意要求,即:第1个出圈的编号存放在p[0]中,第2个出圈的编号存放在p[1]中,直至第n个出圈的编号存放在p[n-1]中。*/
for(i=0,j=n-1;i<n,j>=0;i++,j--) /*也可改为for(i=0,j=n-1;i<n;i++,j--) */
q[j]=p[i];
for(i=0;i<n;i++)
p[i]=q[i];
}
void main()
{
m = M ;
n = N ;
s = S ;
Josegh() ;
WriteDat() ;
}
void WriteDat(void) /*注意两种题中此函数的区别*/
{
int i, j = 0 ;
FILE *fp ;
fp = fopen("out.dat", "w") ;
for(i = 0 ; i <= N - 1 ; i++) {
printf("%4d ", p[i]) ;
fprintf(fp, "%4d", p[i]) ;
j++ ;
if(j % 10 == 0) {
printf("\n") ;
fprintf(fp, "\n") ;
}
}
fclose(fp) ;
}
温馨提示:内容为网友见解,仅供参考
第1个回答  2007-09-23
{ s1=(s1+m-1)%i; \* 下一个开始报数人的编号是(s1+m-1)%i*\
if(s1==0) \*如果s1为0,就说明最后一个报完数,有重新从第一个开始报*\
s1=i;
w=p[s1-1]; \*用循环将出圈的人移到数组最后*\
for(j=s1;j<=i-1;j++)
p[j-1]=p[j];
p[i-1]=w;

计算机三级考试约瑟夫环出圈求解释 wait on line!
} \/*由于上面的解法是倒着存放出圈数,以下采用两个循环的是将数组p中的数据倒过来以实现题意要求,即:第1个出圈的编号存放在p[0]中,第2个出圈的编号存放在p[1]中,直至第n个出圈的编号存放在p[n-1]中。*\/ for(i=0,j=n-1;i<n,j>=0;i++,j--) \/*也可改为for(i=0,j=n-1;...

相似回答
大家正在搜