题目描述
问题
n个小孩围坐成一圈,并按顺时针编号为1,2,…,,从编号为p 的小孩顺时针依次报数,由1报到m,报到m时,这名小孩从圈中出去;然后下一名小孩再从1报数,报到m 时再出去。以此类推,直到所有小孩都从圈中出去。请按出去的先后顺序输出小孩的编号。
输入
第一个是n,第二个是p,第三个是 m(0<m,n<300)。
最后一行是:0 0 0。
输出
按出圈的顺序输出编号,编号之间以逗号间隔。
样例输入
8 3 4
0 0 0
样例输出:
6 2 7 4 3 5 1 8
解答
这道题是著名约瑟夫问题的变体。当约瑟夫问题的数据规模不大时,可以考虑直接利用循环队列进行模拟进行求解。
C代码
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
queue<int> children;
int main(){
int n,p,m;
while(scanf("%d %d %d",&n,&p,&m) != EOF){
//入队
for(int i = 1;i <= n;i++){
children.push(i);
}
//使编号为p的小孩在队首
for (int i = 1; i < p; i++) {
children.push(children.front());
children.pop();
}
//开始输出
while(!children.empty()){
for(int i = 1;i < m;i++){
children.push(children.front());
children.pop();
}
if(children.size() == 1){
printf("%d\n",children.front());
}else{
printf("%d ",children.front());
}
children.pop();
}
}
}
Java代码
import java.util.Scanner;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Queue<Integer> children = new LinkedList<>();
while(scanner.hasNext()){
int n = scanner.nextInt();
int p = scanner.nextInt();
int m = scanner.nextInt();
//加入队列
for (int i = 1;i <= n;i++){
children.offer(i);
}
//使p孩子在队首
for(int i = 1;i < p;i++){
children.offer(children.peek());
children.poll();
}
//开始输出
while (!children.isEmpty()){
for (int i = 1; i < m; i++) {
children.offer(children.peek());
children.poll();
}
if(children.size() == 1){
System.out.print(children.poll() + "\n");
}else {
System.out.printf(children.poll() + " ");
}
}
}
}
}