一、队列的基本使用
#include<queue>
using namespace std;
queue<int>myQueue;
入队:push
出队:pop
判断为空:empty
队首元素:front
queue<int>myQueue;
for(int i=0;i<5;i++){
myQueue.push(i);
}
while(true){
if(myQueue.empty()){
printf("myQueue is empty!");
break;
}
printf("front of myQueue is %d\n",myQueue.front());
myQueue.pop();
}
二、问题
1.约瑟夫问题
描述:
n个小孩围坐一圈,并被顺时针编号为1,2,…,n,从编号为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
解题思路
- 从p到p-1入队
- 从队首开始,报数,出队
- 检查以下,报数是否是m,是不归队,不是归队
小技巧:循环队列——>先出队再入队
代码
#include<queue>
#include<cstdio>
using namespace std;
int main() {
int n, p, m;
while (true) {
scanf_s("%d%d%d", &n, &p, &m);
if (n == 0 && p == 0 && m == 0) {
break;
}
queue<int>children;//孩子的编号
//把第一轮要喊编号的孩子排好队
for (int i = p, j = 0; j < n; ++j) {
//i用来遍历孩子的编号
//j用来记录已经遍历的孩子的数量
children.push(i);
++i;//p->p+1->...->n->1->...->p-1
if (i > n) {
i = 1;
}
}
//喊号的过程
int num = 1;//将要喊的编号
while (true) {
int cur = children.front();//cur是队首孩子的编号
children.pop();//喊完了,队首出队
if (num == m) {//检查以下刚才喊号的号码是不是m
num = 1;//下一个同学喊的号就是1
//喊号的同学不需要归队
if (children.empty()) {
printf("%d\n", cur);
break;
}else {
//还有同学再喊号
printf("%d,", cur);
}
}else {
//需要归队
num += 1; children.push(cur);
}
}
}
}
2、猫狗收容所
描述:
有家动物收容所只收留猫和狗,但有特殊的收容规则。收养人有两种收养方式:
第一种为直接收养所有动物中最早收入收容所的。
第二种为选择收养动物的类型(猫或狗),并收养该种动物最早进入收容所的
给定一个操作序列代表所有的事件。
若第一个元素为1,则代表有动物进入收容所。第二个元素为动物的编号,正数代表狗,负数代表猫。
若第一个元素为2,则代表有人收养动物。第二个若为0,则采取第一种收养方式;若为1,则指定收养狗;若为-1,则指定收养猫。
请按顺序输出收养动物的序列。
若出现不合法的操作,即没有可以符合领养要求的动物,则将这次领养操作忽略。
输入:
第一个是n,它代表操作序列的次数,接下来是n行,每行有两个值m和t,分别代表题目中操作的两个元素
输出:
按顺序输出收养动物的序列,编号之间以空格间隔
样例
输入:
6
1 1
1 - 1
2 0
1 2
2 -1
2 1
输出:
1 -1 2
解题思路
维护两个队列,cat,dog,两个队列要记录插入的次序
代码
#include<queue>
#include<cstdio>
using namespace std;
struct Animal {
int num;
int seq;
};
int main() {
queue<Animal>catQue;
queue<Animal>dogQue;
int seq = 0;
int n;
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
int method, para;
scanf_s("%d%d", &method, ¶);
if (method == 1) {
//入队 para代表动物的编号
if (para > 0) {
//处理狗
Animal dog;
dog.num = para;
dog.seq = seq;
++seq;
dogQue.push(dog);
}
else {
//处理猫
Animal cat;
cat.num = para;
cat.seq = seq;
++seq;
catQue.push(cat);
}
}
else {
//出队
if (para == 0) {
//不区分猫狗
//1.无猫无狗
if (dogQue.empty() && catQue.empty()) {
continue;//跳过本次循环
}
//2.收养狗
//2.a狗非空,猫空
//2.b狗非空,猫非空,队首狗的序号小一点
else if (catQue.empty() ||!dogQue.empty()&& !catQue.empty() && dogQue.front().seq < catQue.front().seq) {
printf("%d ", dogQue.front().num);
dogQue.pop();
}
else {
printf("%d ", catQue.front().num);
catQue.pop();
}
}
else if(para==1){
//领养狗
if (dogQue.empty()) {
continue;
}
printf("%d ", dogQue.front().num);
dogQue.pop();
}
else {
//领养猫
if (catQue.empty()) {
continue;
}
printf("%d ", catQue.front().num);
catQue.pop();
}
printf("\n");
}
}
}