约瑟夫问题:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
利用循环链表求解:
#include<stdio.h>
struct node
{
int num;
struct node *next;
};
void joesphus(int n, int k, int m)
{
//构造循环链表
struct node *head,*p1,*p2;
int i;
p1 = p2 = (struct node*)malloc(sizeof(struct node));
head = p1;
head->num = 1;
for(i = 1; i < n; i++)
{
p1 = (struct node*)malloc(sizeof(struct node));
if(p1 == NULL)
{
return;
}
p1->num = i + 1;
p2->next = p1;
p2 = p1;
}
p2->next = head;
//移到指定的开始位置K
for(i = 1; i < k; i++)
{
head = head->next;
}
//求解,其中q指向p的前一位置,方便报数m的节点的删除操作
struct node *p =head;
int cnt = 1;
while(p != p->next)
{
struct node *q = p;
p = p->next;
cnt++;
if(cnt == m)
{
struct node *temp = p;
q->next = p->next;
p = p->next;
printf("%d\n",temp->num);
free(temp);
cnt = 1;
}
}
printf("the last:%d\n",p->num);
free(p);
}
int main()
{
int n,k,m;
printf("pleast input the n, k and m:\n");
scanf("%d,%d,%d",&n,&k,&m);
joesphus(n, k, m);
return 0;
}
数学方法求解:(待续)