约瑟夫环问题
由古罗马的史学家约瑟夫(Josephus)提出这样一个问题。问题描述为:编号为1, 2,… n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的那个人出列,将他的密码作为新的m值,从头开始重新从1报数,数到m的那个人又出列;如此下去,直至圆桌周围的人全部出列为止。
#示例
假定密码始终为2

输入:
1 2
2 2
3 2
4 2
5 2
输出: 1 2
解释:因为每次从1开始数两个(包括1);
#include <stdio.h>
#include <stdlib.h>
typedef struct lp{
int order; //序号
int digit; //密码m
struct lp *next;
}loop;
int make(loop *list); //制作一个循环链表
void del(loop *list,int m,int *cnt); //删除指定m的元素
int main(int argc,char const* argv[])
{
int m;
int cnt; //记录有多少个节点
loop *list = (loop*)malloc(sizeof(loop));
list->next = NULL;
printf("请输入序号和密码\n");
cnt = make(list);
printf("请输入一个密码m\n");
scanf("%d",&m);
del(list,m,&cnt);
return 0;
}
int make(loop *list)
{
int cnt;
int n,n1;
loop *now = list;
while(scanf("%d %d",&n,&n1) != EOF)
{
loop *p = (loop*)malloc(sizeof(loop)); //制作一个节点
p->order = n;
p->digit = n1;
p->next = NULL;
while(now->next)
{
now = now->next;
}
now->next = p;
cnt ++;
}
/*表尾与表头的下一个节点连接*/
now = now->next;
now->next = list->next;
return cnt;
}
void del(loop *list,int m,int *cnt)
{
int number = 0;
loop *i,*t;
for(i = list->next,t = list; t; t=i,i=i->next)
{
number++; //数的次数加一
/*判断数的次数是不是与秘密相同,相同则释放掉对应节点内存*/
if(number == m)
{
t->next = i->next;
m = i->digit;
free(i);
break;
}
}
*cnt = *cnt - 1; //每执行一次节点数减一
/*当节点数等于1时输出对应的序号,密码*/
if(*cnt > 1)
{
del(list,m,cnt);
}
else{
printf("保留的序号和密码为:\n");
printf("%d\t%d\n",t->order,t->digit);
}
}
8834

被折叠的 条评论
为什么被折叠?



