HDU 1276 士兵队列训练问题(队列)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1276
题目:
士兵队列训练问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8934 Accepted Submission(s): 3947
Problem Description
某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。
Input
本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
Output
共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
Sample Input
2
20
40
Sample Output
1 7 19
1 19 37
思路:
报数问题,用队列处理。当前处理到的人必出队,如果不是报到2(或3)的人就再入队尾,反复操作,直到一轮结束,剩下的人不多于3个。注意!不是说不多于3个就立即停止报数,而是要报完一轮再判断。
代码:
1 #include <cstdio> 2 #include <queue> 3 #include <vector> 4 #include <algorithm> 5 #include <iostream> 6 using namespace std; 7 queue<int>q; 8 vector<int>v; 9 void deal(int t){ 10 int cur=1; 11 int num=q.size(); 12 while (cur<num+1) { 13 int x=q.front();q.pop(); 14 if(cur%t!=0) q.push(x); 15 cur++;//报到t的人不再入队 16 } 17 } 18 int main(){ 19 int t,n; 20 cin>>t; 21 while (t--) { 22 v.clear(); 23 cin>>n; 24 for (int i=1; i<=n; i++) q.push(i);//初始入队 25 while (q.size()>3){//轮流处理报数2和3 26 deal(2); 27 if(q.size()>3) deal(3);//上一轮结束如果不多于3人则不继续 28 } 29 while (!q.empty()) { 30 v.push_back(q.front());//将剩余的人存入vector容器 31 q.pop(); 32 } 33 sort(v.begin(), v.end());//因为反复出队入队,所以顺序乱了,再排序一下 34 cout<<v[0]; 35 for (int i=1; i<v.size(); i++) cout<<" "<<v[i]; 36 puts(""); 37 } 38 return 0; 39 }