兵队列训练问题
TimeLimit:1000MS MemoryLimit:32768KB
64-bit integer IO format:%I64d
Problem Description
某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。(注意每轮报数都要全部报完,不是人数不大于3就停止报数)
Input
本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
Output
共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
SampleInput
2 20 40
SampleOutput
1 7 19 1 19 37
思路:这个题第一次看起来我是 没什么思路的(抛弃旺神提示的队列),然后就开始想说用数组模拟,因为我们放进数组的时候本身就是有顺序的,但是处理的时候就有些复杂了,因为数组删除太麻烦;
所以就用队列模拟,在需要的时候把某个元素舍去,而且不打乱原来的顺序,打乱了?那你把队列循环一圈不就行了吗??因为有两种不同的处理方法,所以用一个变量标记一下第几次模拟编序号
放上我的代码,如果有什么不懂就看我的代码上面有注释
1 #include<stdio.h> 2 #include<queue> 3 using namespace std; 4 int main() 5 { 6 int N,n; 7 scanf("%d",&N); 8 while(N--) 9 { 10 queue<int>q;//这个应该都懂的,队列定义; 11 scanf("%d",&n); 12 for(int i=1;i<=n;i++) 13 q.push(i);//把每个人的编号按顺序压入队列 14 int p=1,x,k; 15 while(q.size()>3)////如果还有超过三个人,继续进行编号和排除等操作 16 { 17 x=q.size();////目前一共有多少人 18 if(p&1)//如果是第奇数次,那么就是从 1 到 2 编号 19 { 20 for(int i=0;i<x/2;i++)//循环操作 21 { 22 k=q.front();//取出编号为1的 23 q.push(k);//把编号为 1 的放后边,入队 24 q.pop();////抛弃编号为 1 (已经放后面了,这个就不需要了) 25 q.pop();//现在弹出的编号为 2 ,抛弃... 26 } 27 if(x&1) 28 { 29 k=q.front();//如果刚开始的时候为奇数个,那么最后还有一个人没被循环过.... 30 q.push(k);//放队尾 31 q.pop();//抛弃. 32 } 33 } 34 else//第偶数次,那就是从 1 到 3 编号 35 { 36 for(int i=0;i<x/3;i++) 37 { 38 k=q.front();//处理编号为 1 ,处理方式和前面一样 39 q.push(k); 40 q.pop(); 41 k=q.front();q.push(k);//处理编号为 2 42 q.pop(); 43 q.pop();//抛弃编号为 3 的 44 } 45 while(x%3!=0)//这里和前面的道理一样,防止有人未处理完 46 { 47 --x; 48 k=q.front();//处理剩余的那几个 49 q.push(k); 50 q.pop(); 51 } 52 } 53 p++; 54 } 55 while(q.size()!=1)//输出 56 { 57 printf("%d ",q.front()); 58 q.pop(); 59 } 60 printf("%d ",q.front()); 61 } 62 return 0; 63 }