[PTA]约瑟夫环(Josephus)问题
Posted Billy Miracle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[PTA]约瑟夫环(Josephus)问题相关的知识,希望对你有一定的参考价值。
1. 约瑟夫环(Josephus)问题
编号为1,2,…,n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数)。一开始任选一个正整数m作为报数上限值,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的那个人出列,将他的密码作为新的m值,从他顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列;如此下去,直至圆桌周围的人全部出列为止。要求按出列顺序输出n个人的编号。
输入格式:
第一行输入两个整数,依次表示人数n和初始化密码m,以空格间隔。 第二行依次输入n个整数,分别表示n个人的密码,以空格间隔。
输出格式:
按出列次序输出每个人的编号,以空格间隔。
输入样例:
在这里给出一组输入。例如:
7 20
3 1 7 2 4 8 4
输出样例:
在这里给出相应的输出。例如:
6 1 4 7 2 3 5
//结尾无空行
Answer:
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
int number;
int password;
struct node * next;
}Node, *List;
int main() {
List head = NULL;
List prev = NULL;
int numbers, password;
scanf("%d%d", &numbers, &password);
for (int i = 1; i <= numbers; i++) {
List pnew = (List)malloc(sizeof(Node));
if (head == NULL) {
head = pnew;
prev = pnew;
}
prev->next = pnew;
pnew->number = i;
scanf("%d", &pnew->password);
pnew->next = head;
prev = pnew;
}
List p = head;
while (p != prev) {
for (int i = 0; i < password - 1; i++) {
p = p->next;
prev = prev->next;
}
password = p->password;
printf("%d ", p->number);
prev->next = p->next;
List t = p;
p = p->next;
free(t);
}
printf("%d ", p->number);
return 0;
}
2. 约瑟夫(Josephus)排列问题Step1
编号为1,2,…,n的n个人按顺时针方向围坐在一张圆桌周围。给定一个正整数m≤n,从第一个人开始按顺时针方向自1开始报数,每报到m时就让其出列,从 他顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列。如此下去,直至圆桌周围的人全部出列为止。每个人的出列次序定义了整数1,2,3,…,n的一个排列。这个 排列称为一个(n,m)Josephus排列。例如:(7,3)Josephus排列为3,6,2,7,5,1,4。
输入格式:
输入两个整数,人数n和密码m,以空格间隔。
输出格式:
按出列次序输出每个人的编号,以空格间隔。
输入样例:
在这里给出一组输入。例如:
7 3
//结尾无空行
输出样例:
在这里给出相应的输出。例如:
3 6 2 7 5 1 4
//结尾无空行
Answer:
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
int number;
struct node * next;
}Node, *List;
int main() {
List head = (List)malloc(sizeof(Node));
head->next = head;
List prev = head;
int numbers, password;
scanf("%d%d", &numbers, &password);
for (int i = 1; i <= numbers; i++) {
List pnew = (List)malloc(sizeof(Node));
prev->next = pnew;
pnew->number = i;
pnew->next = head;
prev = pnew;
}
List p = head->next;
prev = head;
while (head->next != head) {
for (int i = 0; i < password - 1; i++) {
if (p->next == head) {
p = p->next;
prev = prev->next;
}
p = p->next;
prev = prev->next;
}
if (p->next == head) {
printf("%d ", p->number);
prev->next = head;
prev = head;
List t = p;
p = head->next;
free(t);
} else {
printf("%d ", p->number);
prev->next = p->next;
List t = p;
p = p->next;
free(t);
}
}
return 0;
}
3. 约瑟夫(Josephus)排列问题Step2
对于给定的1,2,3,…,n中的k个数,Josephus想知道是否存在一个正整数m(m≤n),使得Josephus(n,m)排列的最后k个数恰好为事先指定的k个数。例如当n为7,k为4,指定排列的最后k个数为7,5,1,4时;由于(7,3)Josephus排列为3,6,2,7,5,1,4;所以求得m值为3。
输入格式:
第一行输入m以及k, 第二行依次指定的k个数,以空格间隔。
输出格式:
如果存在满足条件的正整数m, 则输出m;否则输出0。
输入样例:
在这里给出一组输入。例如:
7 4
7 5 1 4
输出样例:
在这里给出相应的输出。例如:
3
//结尾无空行
Answer:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int number;
struct node * next;
}Node, *List;
List head = NULL;
List pFront = NULL;
List per = NULL;
int n, m;
int b[100], k;
void Create();
void Joseph(int number, int m);
int main() {
scanf("%d %d", &n, &m);
int i;
int a[n];
for (i = n - m ; i < n; i++) {
scanf("%d", &a[i]);
}
for (i = 1; i <= n; i++) {
head = NULL;
pFront = NULL;
k = 0;
int flag = 1;
Create();
per = head;
Joseph(n, i);
for (int j = n - m; j < n; j++) {
if (a[j] != b[j]) {
flag = 0;
}
}
if (flag == 1) {
printf("%d", i);
return 0;
}
}
return 0;
}
void Create() {
List tail;
for (int i = 0; i < n; i++) {
List pnew;
pnew = (List) malloc(sizeof(Node));
pnew->number = i + 1;
if (head == NULL) {
head = pnew;
} else {
tail->next = pnew;
}
tail = pnew;
}
tail->next = head;
pFront = tail;
}
void Joseph(int number, int m) {
if (number == 0) {
return;
}
int count = 1;
List p = NULL;
while (count != m) {
per = per->next;
pFront = pFront->next;
count++;
}
p = per;
pFront->next = per->next;
if(number == 1) {
b[k++] = p->number;
} else {
b[k++] = p->number;
}
per = per->next;
free(p);
Joseph(number - 1, m);
}
以上是关于[PTA]约瑟夫环(Josephus)问题的主要内容,如果未能解决你的问题,请参考以下文章