约瑟夫问题
首先约瑟夫问题: 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
现在解决的是一个类似的问题
17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。
**问题的思路
- 创建一个环链表 就可以不断的遍历
- 然后就得给每个节点赋值了 使用尾插法的话就得从30开始赋值了
- 还有要输出十五个数 那么就得有一个循环来十五次的输出
- 要寻找第九个人而且找到后第十个又从一开始报数
- 这个也可以通过for来寻找,然后空置节点 输出节点数据 释放空间
- 感觉这样一想是挺简单的,但是现在的我敲起来还是挺懵逼的
- 首先搞个结构体
#include <stdio.h>
#include <stdlib.h>
struct node
{
int no;//这是个计数器
struct node *link;
};
typedef struct node G;//相当于结构体的一个别名
- 创建一个空环链表吧
G *head;
head = (G*)malloc(sizeof(G));
head->no=-1;//搭建一个环空链表
head->link=head;//head->link指的是表头节点
至于为什么要有表头节点,表头节点的有无区别在哪里
推荐一篇文章自己看看就懂了
- 再得有个输入
for(i=30;i>0;i--)
{
p = (G*)malloc(sizeof(G));
p->link=head->link;//表头节点的link是head所以p现在指向head
p->no=i;
head->link=p;//再让head指向p
}
- 但是之后的找节点是用不着表头节点的,所以我们将它空置
while(p->link!=head)
p=p->link;//找出最后一个节点
p->link=head->link;//让最后一个节点指向第一个数据节点,空出表头节点
- 下一步就是问题解决的核心了
for(j=0;j<15;j++)//找十五个数
{
for(m=1;m<9;m++)//第九个删掉
p=p->link;//找到第八个
q=p->link;//找到第九个
p->link=q->link;//让第八个指向第十个,空出第九个
printf("%d\n",q->no);
free(q);//释放第九个的空间
}
这样就找出了一种排法,使每次投入大海的都是非教徒。
- 下面是测试代码
#include <stdio.h>
#include <stdlib.h>
struct node
{
int no;
struct node *link;
};
typedef struct node G;
int main()
{
G *p,*q,*head;int i,j,m;
head = (G*)malloc(sizeof(G));
head->no=-1;//搭建一个环空链表
head->link=head;//head->link指的是表头节点
for(i=30;i>0;i--)
{
p = (G*)malloc(sizeof(G));
p->link=head->link;//表头节点的link是head所以p现在指向head
p->no=i;
head->link=p;//再让head指向p
}
while(p->link!=head)
p=p->link;//找出最后一个节点
p->link=head->link;//让最后一个节点指向第一个数据节点,空出表头节点
printf("非教徒的排法:");
for(j=0;j<15;j++)//找十五个数
{
for(m=1;m<9;m++)//第九个删掉
p=p->link;//找到第八个
q=p->link;//找到第九个
p->link=q->link;//让第八个指向第十个,空出第九个
printf("%3d",q->no);
free(q);//释放删掉的空间
}
return 0;
}
2019/12/11 21:56