说明
约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。
输入格式
每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 < m,n <=300)。最后一行是: 0 0
输出格式
对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号
样例
输入数据
6 2
12 4
8 3
0 0
输出数据
5
1
7
今天来解决这一道题,经典的约瑟夫问题
老规矩,直接上码,边看边讲
//代码不十分复杂,使用到了队列(队列处理约瑟夫是真的很方便)
#include <bits/stdc++.h>
using namespace std;
int main(){
//首先定义一个队列
queue <int> q;
//定义两个数组,分别存储猴子数量和出局序号
int nn[500], mm[500];
//变量len储存上面数组的长度,biao表示当前下标,下面有体现
int len= 0,biao = 0;
//因为输入数量无限制,直到0 0才结束,所以设置结束判断
while(true){
cin >> nn[biao] >> mm[biao];
if (nn[biao] == 0 && mm[biao] == 0) break;//结束判断
len++;
biao++;
}//每次输入都要使长度和下标++
//开始循环
for (int i = 0; i< len; i++){
//将数据存入队列
for (int j = 1; j <= nn[i];j++){
q.push(j);
}
//记录出局序号;当出局序号达到要求时,将第一个人出局;当还剩一人时停止转圈,立刻输出
int count = 0;
while(q.size() > 1){
count++;
if (count == mm[i]){
q.pop();
count = 0;
}
else{
int t = q.front();
q.pop();
q.push(t);
}
}
cout << q.front() << endl;
q.pop();//最后要记得将队列清空(只剩下了一只猴王,清一次就可以)
}
return 0;
}
搞定了,测试结果完全正确
不过我仍然坚信还有改进的空间,如果有更好的建议可以留下您宝贵的评论
感谢您的指点