P1996 约瑟夫问题
约瑟夫问题解法
解法一:STL队列实现
#include <iostream> #include <queue> using namespace std; int main() { int n, m; cin >> n >> m; queue<int> q; // 初始化队列,将所有人按顺序加入队列 for (int i = 1; i <= n; i++) { q.push(i); } while (q.size()) { // 将前m-1个人从队首取出并放到队尾 for (int i = 1; i < m; i++) { q.push(q.front()); q.pop(); } // 第m个人出列 cout << q.front() << " "; q.pop(); } return 0; }
思路解析:
-
使用STL的queue来模拟环形结构
-
所有人按顺序入队
-
每次处理时,将前m-1个人从队首移动到队尾
-
第m个人就是当前队首元素,输出并出队
-
重复上述过程直到队列为空
解法二:数组模拟队列
#include<bits/stdc++.h> // 包含所有标准库头文件 using namespace std; const int N = 1e2 + 10; // 定义常量N为110,作为队列大小 int q[N * N]; // 定义队列数组,大小足够大 int head, tail; // 定义队首和队尾指针 int n, m; // 定义总人数n和报数m int main() { cin >> n >> m; // 输入总人数n和报数m // 初始化队列,将所有人按顺序加入队列 for(int i = 1; i <= n; i++) q[tail++] = i; // 将i放入队尾,tail指针后移 int id = 1; // 初始化报数计数器 while(head < tail) // 当队列不为空时循环 { if(id % m == 0) { // 如果当前报数是m的倍数 cout << q[head] << " "; // 输出当前队首的人(出圈) head++; // 队首指针后移,相当于出队 } if(id % m != 0) { // 如果当前报数不是m的倍数 q[tail++] = q[head]; // 将队首的人移到队尾 head++; // 队首指针后移 } id++; // 报数计数器增加 } return 0; }
代码逻辑解析:
-
队列初始化:将1到n的数字依次放入队列中
-
循环处理:
-
使用
id计数器记录当前报数 -
当
id是m的倍数时,当前队首的人出圈(输出并移出队列) -
当
id不是m的倍数时,将当前队首的人移到队尾
-
-
循环条件:当队首指针
head小于队尾指针tail时,表示队列中还有人
注意事项:
-
队列大小
N*N设置得足够大,确保不会溢出 -
head指针始终指向当前队首元素 -
tail指针始终指向队尾下一个可插入位置 -
每次操作后
id都会自增,保证报数连续

浙公网安备 33010602011771号