约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题。在计算机编程的算法中,类似问题又称为约瑟夫环。又称“丢手绢问题”.)
问题:设编号为1,2,...,n的n个人按顺时针方向坐成一排,每个人都有一个正整数密码,开始时任意选一个正整数m(m<n),从第一个人开始按顺时针方向自1起顺序报数,报到m时停止报数,报到m的人出列,其他的密码作为新的m值,从他在顺时针方向上的下一个人起重新从1开始报数,如此下去,直到所有的人全部出列为止。
思路:用顺序存储结构存储每个人的编号,定义一个数组a,数组元素从0开始,所以初始时a[i]存放人的编号为i+1,用计数器count来表示每个人报到的编号,当count==m时,报到count的元素编号变为0表示出列,用d表示出列人数,当d==n的时候结束循环
输入:10, 4
输出:4,8,2,7,3,10,9,1,6,5
#include<stdio.h>
int main()
{
int m,n,i,d=0,count=0; //d控制出列的个数
int a[255];
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
a[i]=i+1; //给a赋初始值
while(d<n)
for(i=0;i<n;i++)
if(a[i]!=0)
{
count++; //计数器开始从0报数
if(count==m) //报数到m的人出列
{
printf("%d ",a[i]);
a[i]=0;
count=0; //从出列的下一位人继续从0开始报数
d++;
}
}
return 0;
}
子问题:猴子选王
问题:一堆猴子都有编号,编号是1,2,3 ...m,这群猴子(m个)按照1-m的顺序围坐一圈,从第1开始数,每数到第N个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。
思路:要找到哪只猴子是大王就是为了找到最后一个出列的元素,这时和上面的思路一样,我们只需要用一个if语句来控制程序打印出最后一个元素便可以解决了
输入:10,4
输出:5
#include<stdio.h>
int main()
{
int m,n,i,d=0,count=0;
int a[255];
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
a[i]=i+1;
while(d<n)
for(i=0;i<n;i++)
if(a[i]!=0)
{
count++;
if(count==m)
{
if(d==n-1) printf("%d",a[i]);//当d为最后一个元素出列的时候打印出该值
a[i]=0;
count=0;
d++;
}
}
return 0;
}
总的来说,约瑟夫问题并不难,但求解的方法很多;题目的变化形式也很多,我们用可以用一个循环的链表来表示,也可以使用结构数组来构成一个循环链,本文章用的就是结构数组来构成循环链。