士兵队列训练问题
Title Description
某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。
Input
本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
Output
共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
Sample Input
2
20
40
Sample Output
1 7 19
1 19 37
思路:
运用队列的思想,想象士兵站成一个圈。就像约瑟夫环。同样的思想。
AC代码:
#include<stdio.h>
#include<string.h>
int main()
{
int t,n,i;
while(~scanf("%d",&t)) //多组输入
{
while(t--) //t组输入
{
int x=0; //计数器用来记是否为最后一个,如过时换行,不是就打一个空格(格式要求)
int k=1; //用来判断是叫到2的人出列还是3出列,我定义的是k=1时喊二出列,-1时喊三出列
int a[5050]={0}; //定义一个数组存士兵出列情况,判断是否出列,将出列的赋值为1,没出列的赋值为0
scanf("%d",&n);
int cnt=n; //士兵人数
//前三中有点特殊需要单独判断,直接判断输出即可,剩下的再进行判断
if(n==1)
{
printf("1\n");continue;
}
else if(n==2)
{
printf("1 2\n");continue;
}
else if(n==3)
{
printf("1 2 3\n");continue;
}
else{
while(1) //定义一个死循环,后面写一个跳出循环的条件就,人数小与等于3
{
x=0;
for(i=1;i<=n;i++)
{
if(k==1) //喊2的时候
{
if(a[i]==0)
{
x++;
}
if(x==2)
{
a[i]=1; //出列士兵记录
cnt--; //士兵人数减一
x=0;
}
}
if(k==-1) //喊3的时候
{
if(a[i]==0)
{
x++;
}
if(x==3)
{
a[i]=1; //出列士兵记录
cnt--; //士兵人数减一
x=0;
}
}
}
k=-k; //题目中说一轮3一轮2,在这是交换
if(cnt<=3) //人数小于等于3时跳出循环
{
break;
}
}
}
x=0;
for(i=1;i<=n;i++)
{
if(a[i]!=1)
{
if(x!=0) // !0时输出空格
printf(" ");
printf("%d",i);
x++;
}
}
printf("\n");
}
}
return 0;
}