网站建设的公司企业管理咨询
约瑟夫问题
OpenJudge - 3254:约瑟夫问题No.2
输入: 每行是用空格分开的三个整数,第一个是n,第二个是p,第三个是m (0 < m,n < 300)。
最后一行是:0 0 0
(即n个人围成一圈,从p号开始抱起,当报到m时就退圈)
输出: 按出圈的顺序输出编号,编号之间以逗号间隔。
思路:
我们可知,先到的小孩先报数,所以我们需要借助一个队列;
而且我们需要实现的是一个循环队列(因为一个小孩报完数,后面可能还需要他再报数)我们可以通过将一个数出队再入队的时候实现循环队列;
-
将n个小孩放入队列(no是他们的编号)
-
第一轮报数(用say表示),从p开始报;我们一开始让着n个元素入队的时候就可以用报数的顺序进行入队。
-
后续报数:报数即为取出队首元素;打印他的值。
如果报的数不是m,则say++,再将该元素放回队列
如果报的数是m,取出队首元素后,若队列不为空,则直接打印元素;若队列为空,则打印元素并退出循环。
int main() {
queue<int> myQueue;int n, p, m;while (1) {//第一个是n,第二个是p,第三个是m scanf("%d%d%d", &n, &p, &m);if (n == 0 && p == 0 && m == 0) {break;}//生成第一轮报数的队列(即将孩子编号放入队列)//p,p+1,.....n,1,2,....p-1int no = p;//no是孩子编号for (int i = 0; i < n; i++) {myQueue.push(no);no++;if (no > n) {no = 1;}}
//开始报数 int say = 1;while (1) {int cur = myQueue.front();myQueue.pop();//如果报的数是mif (say == m) {say = 1;//该小孩读到了m,且出去后队列为空;这时打印完其编号后就退出循环了。if (myQueue.empty()) {printf("%d\n", cur);break;}else {printf("%d,", cur);}}else {//如果报的数字不是msay++;//把该小孩重新放回队列中myQueue.push(cur);
}}}
}