某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。
Input
本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
Output
共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
Sample Input
2 20 40
Sample Output
1 7 19 1 19 37
解题思路:
这个题目我们这样去思考,如果这个队列中的人数是小于等于3的,这个循环就结束了。如果是大于3的,我们就要进行这样的操作,给定一个first做标记,首先我们将这个数组遍历一次,没提取一个数组元素,就让first加一,当first等于2时就让first又重新变为0;同时将士兵的总数s减一并将这时的元素做一个标记,将它赋值为0。(这样就将报数报到2的士兵标记出来了)。然后要判断一次此时的士兵总数s是否小于等于3;如果不是,就有做一次类似上面的操作这时的first要重新赋值为0而且要当first等于3时。注意每次遍历的时候都要求这时的元素是不为0的。最后输出的时候要注意空格的输出。输出的时候又是进行一次遍历,要求此时的元素不是0.因为这个程序的循环次数很多,所以要注意时间的耗费.
程序代码:
#include <iostream> using namespace std; int a[5005]; int main() { int n,first; cin>>n; while(n--) { int c,s; cin>>c; s=c; for(int i=1;i<=c;i++) a[i]=i; if(c<=3) { cout<<"1"; for(int j=2;j<=c;j++) cout<<" "<<a[j]; cout<<endl; continue; } while(1) { if(s>3) { first=0; for(int k=1;k<=c;k++) { if(a[k]) first++; if(first==2) { a[k]=0; first=0; s--; } } } if(s>3) { first=0; for(int l=1;l<=c;l++) { if(a[l]) first++; if(first==3) { a[l]=0; first=0; s--; } } } if(s<=3) break; } cout<<"1"; s--; for(int h=2;s;h++) { if(a[h]) { cout<<" "<<a[h]; s--; } } cout<<endl; } return 0; }