约瑟夫问题
约瑟夫环问题(Josephus)

算法设计
Josephus jp=new Josephus(); int a[]=new int[n]; for(int i=0;i<n;i++){ a[i]=i+1; } jp.SortArray(a,n,m,k,g); } public void show(int[]b,int g){ for(int i=b.length-g;i<b.length;i++){ System.out.print(b[i]+" "); } }
• b[c]=a[i]; • a[i]=0; • c++; • if(c==n) break; • } • System.out.print(“最后出列的 3人: "); • this.show(b,g); • } • }
• 1.数据选择: 要求:n<2^15; 1<=k<=n; 2.数据和结果显示:
(3)当然其中还是会存在一些漏洞,需要进 一步的改进。在计算机中是容不得丝毫的 错误的,这也让我们学到了面对科学要持 有严谨的态度,否则必定得不到应该有的 结果。
总人数n 起始号码k 循环数m 最后出列的3人 总人数n 起始号码k 循环数m 最后出列的3人 总人数n 起始号码k 循环数m 最后出列的3人 48 6 15 47 21 46 105 73 4 87 32 21 300 80 12 70 296 198 总人数n 起始号码k 循环数m 68 34 25
输出格式:
T行最后min(n,3)个出列的编号。 结果:6 1 5
问题背景
• 这个问题是以弗拉维奥•约瑟夫斯命名的, 它是1世纪的一名犹太历史学家。他在自己 的日记中写道,他和他的40个战友被罗马 军队包围在洞中。他们讨论是自杀还是被 俘,最终决定自杀,并以抽签的方式决定 谁杀掉谁。约瑟夫斯和另外一个人是最后 两个留下的人。约瑟夫斯说服了那个人, 他们将向罗马军队投降,不再自杀。
约瑟夫问题

约瑟夫问题
1
问题描述
n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号。
输入格式:
n和m两个整数,中间用空格隔开。
m,n<=100。
输出格式:
出圈的编号。
输入样例:
10 3
输出样例:
3 6 9 2 7 1 8 5 10 4
2
问题分析
这是典型的约瑟夫问题,我们这里用模拟的方法。
利用循环一个一个数,定义一个计数变量count,表示记录从1开始数的人数;定义一个下标索引变量i,表示数的人所在的位置下标。
另外还要定义个记录出去人数的变量t。
循环的条件是t<=n。
我们用数组对应的值表示该下标的人是否出去了。
0表示存在,1表示出去。
如果数到最后一个记得还要从第一个开始。
3
参考代码如下。
约瑟夫问题及变种

“约瑟夫”问题及若干变种例1、约瑟夫问题(Josephus)[问题描述]M只猴子要选大王,选举办法如下:所有猴子按1…M编号围坐一圈,从第1号开始按顺序1,2,…,N 报数,凡报到N的猴子退出到圈外,再从下一个猴子开始继续1~ N报数,如此循环,直到圈内只剩下一只猴子时,这只猴子就是大王。
M和N由键盘输入,1≤N,M≤10000,打印出最后剩下的那只猴子的编号。
例如,输入8 3,输出:7。
[问题分析1]这个例题是由古罗马著名史学家Josephus提出的问题演变而来的,所以通常称为Josephus(约瑟夫)问题。
在确定程序设计方法之前首先来考虑如何组织数据,由于要记录m只猴子的状态,可利用含m个元素的数组monkey来实现。
利用元素下标代表猴子的编号,元素的值表示猴子的状态,用monkey[k]=1表示第k只猴子仍在圈中,monkey[k]=0则表示第k只猴子已经出圈。
程序采用模拟选举过程的方法,设变量count表示计数器,开始报数前将count置为0,设变量current 表示当前报数的猴子编号,初始时也置为0,设变量out记录出圈猴子数,初始时也置为0。
每次报数都把monkey[current]的值加到count上,这样做的好处是直接避开了已出圈的猴子(因为它们对应的monkey[current]值为0),当count=n时,就对当前报数的猴子作出圈处理,即:monkey[current]:=0,count:=0,out:=out+1。
然后继续往下报数,直到圈中只剩一只猴子为止(即out=m-1)。
参考程序如下:program josephus1a {模拟法,用数组下标表示猴子的编号}const maxm=10000;var m,n,count,current,out,i:integer;monkey:array [1..maxm] of integer;beginwrite('Input m,n:');readln(m,n);for i:=1 to m do monkey[i]:=1;out:=0; count:=0; current:=0;while out<m-1 dobeginwhile count<n dobeginif current<m then current:=current+1 else current:=1;count:=count+monkey[current];end;monkey[current]:=0; out:=out+1; count:=0end;for i:=1 to m doif monkey[i]=1 then writeln('The monkey king is no.',i);readlnend.[运行结果]下划线表示输入Input m,n:8 3The monkey king is no.7 {时间:0秒}Input m,n:10000 1987The monkey king is no.8544 {时间:3秒}[反思]时间复杂度很大O(M*N),对于极限数据会超时。
约瑟夫问题pascal

约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题。
在计算机编程的算法中,类似问题又称为约瑟夫环。
又称“丢手绢问题”)据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
然而Josephus 和他的朋友并不想遵从。
首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。
接着,再越过k-1个人,并杀掉第k个人。
这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。
问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
//详情请见百度百科。
[题目描述]Josephus问题是建立在历史学家Josephus的一个报告的基础之上,该报告讲述了他和40个士兵在公元67年被罗马军队包围期间签定的一个自杀协定,Josephus建议每个人杀死他的邻居,他很聪明的使自己成为这些人中的最后一个,因此获得生还。
21世纪的今天,我们将Josephus问题稍作扩展:设N个人围成一圈,依次从1到N编号,从第S号开始报数,报到K的人出列,求第T个出列的人的编号。
显然,Josephus面对的是N = 40, K = 2, S= 1, T = 40的退化情况。
[数据范围]30%的数据,K = 2100%的数据,1 <= N <= 1000000, 1<= K <= 2147483647, 1 <= S <= N, 1 <= T <= N最简单的推导方法应该是模拟。
实验一、约瑟夫问题

实验一:约瑟夫问题求解一、问题描述1、实验题目:约瑟夫(Josephus)问题的一种描述是:编号为1,2,……,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上线值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。
2、基本要求:试设计一个程序,按出列顺序印出个人编号。
3、测试数据:m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4。
m的初值为6,正确的出列顺序应为:6,1,4,7,2,3,5。
二、需求分析1、本程序用来求出含有密码的约瑟夫问题,可以输出所有人的出列顺序。
2 、程序运行后显示提示信息,提示用户输入一圈的人数n,接着输入每个人的密码,最后提示输入初始密码。
3、用户输入完毕后,程序自动输出运算结果。
三、概要设计1、设计思路n个人围成一圈,每个人的手中都有一个密码,这个密码决定了下一次报数的上限。
游戏规则:①给定一个初始密码②循环报数,报到密码值的人要出列,依次类推,直到所有的人都出列本程序要求输入的内容:n个人的密码及初始密码;本程序要求输出的内容:n个人出列的顺序。
2、数据结构为了实现上述功能,可以采用链式存储结构。
采用链式存储结构,定义了一个存储个人信息的结构体,及两个自定义函数,分别用于创建链表和约瑟夫出列操作。
①链表抽象数据类型的定义: #define SLNODE struct slnodeADT SLNODE{数据对象:D={ i a |i a ∈SLNODE, i=1,2,3.... }数据关系:R=φ}ADT SLNODE;②自定义函数:void create_SLnode(SLNODE *p,int n)//创建队列{ 创建链表,为N 个人分配密码 }void Josef(SLNODE *p,int n)//进行约瑟夫操作{输入初始密码m;for(){ 将出列的结点删除,并输出出列序号;}}③本程序的保护模块:结构体模块主程序模块自定义函数模块调用关系:3、程序设计主要算法的流程图:create_SLnode( )算法流程图Josef( )算法流程图四、详细设计1、元素类型、结点的类型及指针#define SLNODE struct slnodeSLNODE//每个结点的结构体{int num;//num代表序号int code;//code代表密码SLNODE *next;};2、自定义函数:void create_SLnode(SLNODE *p,int n)//创建队列,并将其尾指针指向第一个序号{SLNODE *r,*s;s=p;int i,m;cout<<"请给这"<<n<<"个人分配密码:"<<endl;for(i=0;i<n;i++){cout<<"请给第"<<i+1<<"个人输入密码:"<<endl;cin>>m;r=(SLNODE *)malloc(sizeof(SLNODE));r->code=m;r->num=i+1;r->next=s->next;s->next=r;s=s->next;}p=p->next;s->next=p;}void Josef(SLNODE *p,int n)//进行约瑟夫操作{p=p->next;int m;int i,j;SLNODE *r;cout<<"请输入初始密码:"<<endl;cin>>m;cout<<"依次出列的序号为:"<<endl;for(i=0;i<n-1;i++)p=p->next;for(i=0;i<n-2;i++){for(j=0;j<m-1;j++)p=p->next;cout<<(p->next)->num<<endl;m=(p->next)->code;r=p->next;p->next=r->next;}if(m%2==0)cout<<p->num<<endl<<(p->next)->num<<endl;elsecout<<(p->next)->num<<endl<<p->num<<endl;}3、主函数:int main(){SLNODE *p;int n;cout<<"请输入一圈的人数:"<<endl;cin>>n;p=(SLNODE *)malloc(sizeof(SLNODE));p->next=NULL;create_SLnode(p,n);Josef(p,n);return 0;}4、函数的调用关系:主函数main()调用自定义函数void create_SLnode(SLNODE *p,int n);/*创建队列*/与void Josef(SLNODE *p,int n);/*进行约瑟夫操作*/。
约瑟夫问题

4、狐狸捉兔子
题目:
围绕着山顶有10个洞,狐狸要吃兔子,兔子说:“可以,但必须找到我,我就藏身于这十个洞中,你从10号洞出发,先到1号洞找,第二次隔1个洞找,第三次隔2个洞找,以后如此类推,次数不限。”但狐狸从早到晚进进出出了1000次,仍没有找到兔子。问兔子究竟藏在哪个洞里?
参考程序下载
--------------------------------------------------------------------------------
5、进制转换
题目:
将一个十进制自然数转换成二进制数,一般采取除2取余法。从键盘输入一个十进制自然数(约定该数小于等于Maxlongint),输出相应的二进制数
设有一天平,可用来称物体的质量,同时给出一个正整数n(n<=10)。
问题1:试设计n个砝码的质量,用它们能称出尽可能多的1,2,3,...连续整数质量,约定砝码可以放在天平的左右两个托盘中的任何一个或两个中。例如n=2,此时设计2个砝码的质量分别为1,3,则能同时称取1,2,3,4。
问题2:在给出n个砝码能称出最大质量范围内的一个质量x,试给出称取x的方案。如上例中:
6/7,7/8,1/1
编程求出n级法雷序列,每行输出10个分数。n的值从键盘输入。
--------------------------------------------------------------------------------
13、砝码设计
题目:
①把组成这个四位数的4个数字由小到大排列,形成由这四个数字组成的最大的四位数;
②把组成这个四位数的4个数字由大到小排列,形成由这四个数字组成的最小的四位数(如果含有数字0,则不足四位);
约瑟夫问题大全

“约瑟夫”问题及若干变种林厚从例1、约瑟夫问题(Josephus)[问题描述]M只猴子要选大王,选举办法如下:所有猴子按1…M编号围坐一圈,从第1号开始按顺序1,2,…,N报数,凡报到N的猴子退出到圈外,再从下一个猴子开始继续1~ N报数,如此循环,直到圈内只剩下一只猴子时,这只猴子就是大王。
M和N由键盘输入,1≤N,M≤10000,打印出最后剩下的那只猴子的编号。
例如,输入8 3,输出:7。
[问题分析1]这个例题是由古罗马著名史学家Josephus提出的问题演变而来的,所以通常称为Josephus(约瑟夫)问题。
在确定程序设计方法之前首先来考虑如何组织数据,由于要记录m只猴子的状态,可利用含m 个元素的数组monkey来实现。
利用元素下标代表猴子的编号,元素的值表示猴子的状态,用monkey[k]=1表示第k只猴子仍在圈中,monkey[k]=0则表示第k只猴子已经出圈。
程序采用模拟选举过程的方法,设变量count表示计数器,开始报数前将count置为0,设变量current表示当前报数的猴子编号,初始时也置为0,设变量out记录出圈猴子数,初始时也置为0。
每次报数都把monkey[current]的值加到count上,这样做的好处是直接避开了已出圈的猴子(因为它们对应的monkey[current]值为0),当count=n时,就对当前报数的猴子作出圈处理,即:monkey[current]:=0,count:=0,out:=out+1。
然后继续往下报数,直到圈中只剩一只猴子为止(即out=m-1)。
参考程序如下:program josephus1a {模拟法,用数组下标表示猴子的编号}const maxm=10000;var m,n,count,current,out,i:integer;monkey:array [1..maxm] of integer;beginwrite('Input m,n:');readln(m,n);for i:=1 to m do monkey[i]:=1;out:=0; count:=0; current:=0;while out<m-1 dobeginwhile count<n dobeginif current<m then current:=current+1 else current:=1;count:=count+monkey[current];end;monkey[current]:=0; out:=out+1; count:=0end;for i:=1 to m doif monkey[i]=1 then writeln('The monkey king is no.',i);readlnend.[运行结果]下划线表示输入Input m,n:8 3The monkey king is no.7 {时间:0秒}Input m,n:10000 1987The monkey king is no.8544 {时间:3秒}[反思]时间复杂度很大O(M*N),对于极限数据会超时。
约瑟夫问题实验报告

一、实验目的1. 理解并掌握约瑟夫问题的基本原理和解决方法。
2. 学习使用循环链表解决线性问题。
3. 提高编程能力和算法设计能力。
二、实验原理约瑟夫问题(Josephus Problem)是一个著名的数学问题,也称为约瑟夫环问题。
问题描述为:N个人围成一圈,从第一个人开始按顺时针方向报数,每数到M的人出列,然后从下一个人开始继续报数,直到所有人都出列。
我们需要找到一种方法,计算出每个人出列的顺序。
三、实验内容1. 创建一个循环链表,模拟N个人围成一圈。
2. 编写一个函数,实现报数和出列操作。
3. 输出每个人出列的顺序。
四、实验步骤1. 定义一个循环链表节点结构体,包含编号和指向下一个节点的指针。
2. 创建一个循环链表,包含N个节点,节点的编号依次为1到N。
3. 编写一个函数`kill(int m, int n)`,实现报数和出列操作:- 初始化一个指针指向第一个节点。
- 从第一个节点开始,按照报数上限M进行报数,每数到M的人出列。
- 更新指针,指向下一个节点,继续报数。
- 重复上述步骤,直到所有节点都被删除。
4. 输出每个人出列的顺序。
五、实验代码```c#include <stdio.h>#include <stdlib.h>// 定义循环链表节点结构体typedef struct Node {int number; // 节点编号struct Node next; // 指向下一个节点的指针} Node;// 创建循环链表Node create(int n) {Node head = NULL, tail = NULL, temp = NULL; for (int i = 1; i <= n; i++) {temp = (Node)malloc(sizeof(Node));temp->number = i;temp->next = NULL;if (head == NULL) {head = temp;tail = temp;} else {tail->next = temp;tail = temp;}}tail->next = head; // 形成循环链表return head;}// 输出循环链表void printList(Node head) {Node temp = head;do {printf("%d ", temp->number);temp = temp->next;} while (temp != head);printf("\n");}// 解决约瑟夫问题void josephus(int m, int n) {Node head = create(n);Node temp = head, pre = NULL;for (int i = 1; i <= n; i++) {for (int j = 1; j < m; j++) {pre = temp;temp = temp->next;}printf("%d ", temp->number);pre->next = temp->next; // 删除节点 free(temp);temp = pre->next;}printf("\n");}int main() {int m, n;printf("请输入报数上限M: ");scanf("%d", &m);printf("请输入人数N: ");scanf("%d", &n);printf("初始站队为: ");josephus(m, n);return 0;}```六、实验结果与分析通过运行实验代码,可以得到每个人出列的顺序。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.循环单链表求解约瑟夫问题。
#include<stdio.h>#include<stdlib.h>typedef int DataType;typedef struct node{DataType data;struct node *next;}LNode,*LinkList;LinkList Creat_josephus_LinkList(int n){LinkList h,p,s;DataType x;int i;h=p=(LinkList)malloc(sizeof(LNode));s=h;printf("请输入第1个数据元素:");scanf("%d",&x);s->data=x;s->next=NULL;for(i=1;i<n;i++){printf("请输入第%d个数据元素:",i+1);scanf("%d",&x);s=(LinkList)malloc(sizeof(LNode));s->data=x;s->next=NULL;p->next=s;p=s;}s->next=h;return(h);}int josephus_LinkList(LinkList josephus_Link,int weizhi,int jiange){LinkList p,pre;int i;if(!josephus_Link){printf("表中无元素!");return 0;}p=josephus_Link;for(i=1;i<weizhi;i++)p=p->next;printf("输出约瑟夫序列:");while(p!=p->next){for(i=1;i<jiange;i++){pre=p;p=p->next;}printf("%d\t",p->data);pre->next=p->next;free(p);p=pre->next;}printf("%d\n",p->data);free(p);return 1;}void main(){int weizhi,jiange,n;LinkList josephus_Link;printf("请输入数据元素的个数:");scanf("%d",&n);josephus_Link=Creat_josephus_LinkList(n);printf("请输入开始节点的位置:");scanf("%d",&weizhi);printf("请输入报数间隔大小:");scanf("%d",&jiange);josephus_LinkList(josephus_Link,weizhi,jiange);getchar();}2.顺序表求解约瑟夫问题。
#include<stdio.h>#include<stdlib.h>#define MAXSIZE 100typedef int DataType;typedef struct node{DataType data[MAXSIZE];int length;}SeqList,*PSeqList;PSeqList Creat_josephus_seq(){int i;PSeqList PL;PL=(PSeqList)malloc(sizeof(SeqList));if(PL)PL->length=0;printf("请输入线性表的长度:");scanf("%d",&(PL->length));for(i=0;i<PL->length;i++){printf("数据%d=",i);scanf("%d",&(PL->data[i]));}return(PL);}int Delete_SeqList(PSeqList PL,int i){int j;if(!PL){ printf("表不存在!"); return(-1); }if(i<1||i>PL->length){ printf("删除位置错误!");return 0; }for(j=i;j<PL->length;j++)PL->data[j-1]=PL->data[j];PL->length--;return(1);}int josephus_SeqList(PSeqList josephus_seq,int weizhi,int jiange){int s1,i;if(!josephus_seq->length){ printf("表中无元素!"); return 0; }s1=weizhi-1;printf("输出约瑟夫序列:");for(i=josephus_seq->length;i>0;i--){s1=(s1+jiange-1)%i;printf("%d\t",josephus_seq->data[s1]);Delete_SeqList(josephus_seq,s1+1);}printf("\n");return 1;}void main(){int weizhi,jiange;PSeqList josephus_seq;josephus_seq=Creat_josephus_seq();printf("请输入开始节点的位置:");scanf("%d",&weizhi);printf("请输入报数间隔:");scanf("%d",&jiange);josephus_SeqList(josephus_seq,weizhi,jiange);getchar();}3.静态链表求解约瑟夫问题。
#include<stdio.h>#include<stdlib.h>#define MAXSIZE 100 typedef struct{int data;int next;}SNode;SNode sp[MAXSIZE]; static int SL=0;static int length;Creat_josephus_stlist(){int i,d;for(i=0;i<length;i++){printf("数据%d:",i+1);scanf("%d",&d);sp[i].data=d;sp[i].next=i+1;}sp[length-1].next=0;}void out_josephus_stlist(int length){int i;printf("xiaobiao data next\n");for(i=0;i<length;i++)printf("%d\t%d\t%d\n",i,sp[i].data,sp[i].next); }int josephus_StList(int weizhi,int jiange){int p,pre,temp,i;p=SL;pre=SL;Creat_josephus_stlist(length);out_josephus_stlist(length);for(i=1;i<weizhi;i++)p=sp[p].next;printf("输出约瑟夫序列:\n");while(p!=sp[p].next){for(i=1;i<jiange;i++){pre=p;p=sp[p].next;}printf("%d\t",sp[p].data);temp=sp[pre].next;sp[pre].next=sp[p].next;sp[p].next=temp;p=sp[pre].next;}printf("%d\n",sp[p].data);return 1;}void main(){int weizhi,jiange;printf("请输入静态链表的长度:");scanf("%d",&length);printf("请输入开始节点的位置:");scanf("%d",&weizhi);printf("请输入报数间隔:");scanf("%d",&jiange);josephus_StList(weizhi,jiange);getchar();}。