约瑟夫问题
一个旅行社要从n个旅客中选出一名旅客,为他提供免费的环球旅行服务。旅行社安排这些旅客围成一个圆圈,
从帽子中取出一张纸条,用上面写的正整数m(<n)作为报数值。游戏进行时,从第s个人开始按顺时针方向自1开始顺序报数,
报到m时停止报数,报m的人被淘汰出列,然后从他顺时针方向上的下一个人开始重新报数,如此下去,直到圆圈中只剩下一个人,
这个最后的幸存者就是游戏的胜利者,将得到免费旅行的奖励。
输入说明,输入的第一行表示总的旅客数,输入的第二行表示报数值,输入的第三行表示报数人的起始编号。
输入样例:
9
5
1
输出说明,输出这n个人的淘汰顺序
输出样例:
5
1
7
4
3
6
9
2
一个旅行社要从n个旅客中选出一名旅客,为他提供免费的环球旅行服务。旅行社安排这些旅客围成一个圆圈,
从帽子中取出一张纸条,用上面写的正整数m(<n)作为报数值。游戏进行时,从第s个人开始按顺时针方向自1开始顺序报数,
报到m时停止报数,报m的人被淘汰出列,然后从他顺时针方向上的下一个人开始重新报数,如此下去,直到圆圈中只剩下一个人,
这个最后的幸存者就是游戏的胜利者,将得到免费旅行的奖励。
输入说明,输入的第一行表示总的旅客数,输入的第二行表示报数值,输入的第三行表示报数人的起始编号。
输入样例:
9
5
1
输出说明,输出这n个人的淘汰顺序
输出样例:
5
1
7
4
3
6
9
2
8
#include <stdio.h>
#define N 100
int main()
{
int n,m,s;
scanf("%d%d%d",&n,&m,&s);
int a[N] = {0};//数组初始化
int i,j;
for(i = 0; i < n; i++)//数组遍历
{
a[i] = i+1;
}
i=s-1;//数组起点
while (n > 1)
{
i = (i + m - 1) % n;// 淘汰的人
printf("%d\n",a[i]);
for(j = i+1; j < n; j++)
{
a[j-1] = a[j];
}
n--;
if(i == n)//终点后,开始起点
{
i = 0;
}
}
printf("%d\n", a[i]);
return 0;
}
结果如下:
下面用循环链表解决:
/*约瑟夫问题,单链表实现*/
#include <stdio.h>
#include <malloc.h>
#include <conio.h>//conio是Console Input/Output(控制台输入输出)
typedef struct node{ //循环链表结构
int No;
struct node *next;
}Node,*Link;
Link CreatRing(int n)//创建n个结点的链表
{
int i;
Link head=NULL,tail=NULL;
for(i=1;i<=n;i++){
if(i==1)
head=tail=(Link)malloc(sizeof(Node));
else{
tail->next=(Link)malloc(sizeof(Node));
tail=tail->next;
}
tail->No=i;
tail->next=NULL;
}
tail->next=head; //全部建立完成后将首尾相连形成环
return head; //返回建好的头结点
}
Link Delete(Link s) //删除循环链表中的结点s
{
Link p=s;
while(p->next!=s)
p=p->next;
p->next=s->next;
free(s);
return p->next;//返回结点的下一个结点的指针
}
void Josephu(Link p,int n,int m,int k)//按约瑟夫规则依次输出结点
{
int i,j;
for(i=1;i<k;i++){
p=p->next;
}
for(i=1;i<n;i++){
for(j=1;j<m;j++)
p=p->next;
printf("%d\n",p->No);//将出列人的序号输出
p=Delete(p); //从表中删除该人
}
printf("%d\n",p->No);//将最后出列的人的序号输出
}
int main(void)
{
int n,m,k;
Link head=NULL;
scanf("%d%d%d",&n,&m,&k);
head=CreatRing(n);
Josephu(head,n,m,k);
return 0;
}
运行结果: