C语言编程100例里面的题目,谁给我说下这题的思路

有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。
书上给的答案是

#define nmax 50
int main()
{
int i,k,m,n,num[nmax],*p;
printf("shu ru yi ge shu :");
scanf("%d",&n);
p=num;
for(i=0;i<n;i++)
*(p+i)=i+1;
i=0;
k=0;
m=0;
while(m<n-1)
{
if(*(p+i)!=0) k++;
if(k==3)
{ *(p+i)=0;
k=0;
m++;
}
i++;
if(i==n) i=0;
}
while(*p==0) p++;
printf("%d is left\n",*p);
}

看不太懂,主要是看着没思路,谁帮忙讲讲,谢谢了

这是著名的约瑟夫问题:
约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的人的序号为5,4,6,2,3。最后剩下1号。 假定在圈子里前K个为好人,后K个为坏人,你的任务是确定这样的最少M,使得所有的坏人在第一个好人之前被杀掉。

程序里作一些注释方便你理解

#define nmax 50
int main()
{
int i,k,m,n,num[nmax],*p;
printf("shu ru yi ge shu :");
scanf("%d",&n);
p=num;
for(i=0;i<n;i++)
*(p+i)=i+1;//产生初始值 1,2,3...,n
i=0;
k=0;
m=0;
while(m<n-1)//当有n-1个人出圈了,就停止循环,即找到了最后一个出圈的人
{
if(*(p+i)!=0) k++;//开始计数,如果序号为(i+1)的人没有退出圈子(即他的值不为0时),则计数
if(k==3) //第3个人,则退出圈子,将他那个数组元素清0.
{ *(p+i)=0;
k=0; //计数值清0,重新计算剩下的第3个人的位置。
m++; //计算共有多少人出了圈子。
}
i++;//数组元素偏移量向后移一位 -> *(p+i)
if(i==n) i=0; // 如果数组元素序号超过当前总人数,则循环一圈,从第1个人开始
}
while(*p==0) p++;//找出剩下的那个人的序号,不为0的就是他!
printf("%d is left\n",*p);// 输出结果。OK。
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-08-04
#define nmax 50
int main()
{
int i,k,m,n,num[nmax],*p;
printf("shu ru yi ge shu :");
scanf("%d",&n);//n个人
p=num;//p为此数组首指针
for(i=0;i<n;i++)
*(p+i)=i+1;//把此数组赋值num[0]=0,num[1]=1.....,没啥意义吧,就是用指针赋值非0
i=0;
k=0;
m=0;

while(m<n-1)//m为人员出列数,出了n-1个人则结束
{
if(*(p+i)!=0) k++;//k为计数器,没有报到3的话就是k++

if(k==3)
{ *(p+i)=0;//报到3的数组赋值为0,num[2]=0,num[5]=0...
k=0;//计数器归0
m++;//出列数加1
}

i++;
if(i==n) i=0;//报完一圈
}

while(*p==0) p++;//找到那个不是0元素的值
printf("%d is left\n",*p);//打印出来
}
相似回答