#include<bits/stdc++.h> using namespace std; #include<vector> int main() { int n,m; cin>>n>>m; vector<bool> people(n+1,true); int f=0;//出圈人数 while(f!=n){//所有人出圈 int sum=0; for(int i=0;;i++){ do{ if(people[i]){ sum++; if(sum==m){ sum=0; cout<<(i+1)<<" "; people[i]=false; f++; break; } } i=(i+1)%n;//循环 }while(true); } } }
时间: 2025-03-19 07:09:31 浏览: 37
<<
这段代码的目的是模拟约瑟夫环问题(Josephus Problem),即给定 `n` 个人围成一圈,并从第一个人开始报数,每次报到数字 `m` 的人出圈,直到所有人都出圈为止。
### 回答与改进:
#### **原代码存在的问题及分析**
1. 内层逻辑存在问题:内层循环中使用了双重嵌套的条件判断 (`for (int i = 0;; i++) { do { ... } while(true);}`),导致逻辑复杂且难以理解。
2. 边界处理不够清晰:`i % n` 只能保证索引不会越界,但并没有考虑到部分元素已经被标记为“已出圈”后的实际有效范围缩小的问题。
3. 性能较差:由于直接对整个数组进行遍历并跳过无效值,当 `n` 或者 `m` 值较大时效率低下。
---
#### **优化版本**
下面是重新组织过的、更简洁高效的 C++ 实现方式:
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m; // 输入的人数和步长
cin >> n >> m;
vector<int> people(n);
for (int i = 0; i < n; ++i) {
people[i] = i + 1; // 初始化编号 [1..n]
}
vector<int> result; // 记录最终顺序
int index = -1; // 当前指针位置初始化为-1
int remain = n; // 还剩下多少人未被移除
while (remain > 0) {
int count = 0;
while (count < m) { // 模拟每轮计数过程
index = (index + 1) % n; // 循环移动指针
if (people[index] != 0) { // 如果当前人还没出局,则计入计数值
count++;
}
}
result.push_back(people[index]); // 将该人的编号加入结果集合
people[index] = 0; // 标记此人已经退出圈子
remain--; // 减少剩余人数数量
}
// 输出所有被淘汰者的序号
for (size_t i = 0; i < result.size(); ++i) {
cout << result[i];
if (i != result.size() - 1)
cout << " "; // 非最后一个输出之间加空格分隔符
}
return 0;
}
```
---
### 解释上述代码的工作原理
1. 使用一个大小为 `n` 的整型向量 `vector<int>` 来存储每个人的位置状态。初始情况下,将每个位置设置为其对应的编号 `[1...n]`。
2. 定义变量 `index` 表示当前指向哪个位置;定义另一个变量 `remain` 统计还有多少人在圈子里等待淘汰。
3. 在主循环中,按照指定规则逐步淘汰成员:每当找到第 `m` 个还未被淘汰的人后将其记录下来并将之设为无效(置零)。
4. 最终打印按次序依次被淘汰的所有人的序列。
这种方法避免了大量的重复检查操作,显著提高了程序运行速度尤其对于较大的输入数据集来说表现更加优异。
---
####
阅读全文
相关推荐



















