首页 > 代码库 > 2017/7/17

2017/7/17

二:

士兵队列训练问题 

某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。 

Input本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。 
Output共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
Sample Input

2
20
40

Sample Output

1 7 19
1 19 37

分析:报到2,报到3分别表示可以被2,3整除,刚开始以为是数字中包含2,3.要剔除2,3,然后重排,最后要输出原来的编号。
思路:用三个数组来储存
用a[i]来代表最初的数据,其实数组的下标i就是原来的编号
用b[i]代表是否是2,3的因子,是储存为1,否储存为0
用两个变量来储存总人数
n代表最开始的人数
t代表实时的人数(变化的)
最后吧b[i]==1的赋值给d[i]

源代码:

#include <iostream>

using namespace std;

#include <stdio.h>

#include <math.h>

int a[5001],b[5001];

int main()

{

    int T,n,i,j,k,t,d[4];

    scanf("%d",&T);

    while(T--)

    {

    scanf("%d",&n);

    //n=T;

    for(i=1;i<=n;i++)//i表示最初的编号

    {

        a[i]=i;//初始化排队

        b[i]=1;//全部初始化为1

    }

    t=n;//因为这里面的n会在计算中发生变化,所以要重新赋值,用另一个变量代替它发生变换!

    if(n>3)//n>3的时候,因为需要出列,所以按照题意执行就可以了,记住,执行过之后

    for(j=1;j<=n;j++)//士兵的顺序不发生改变,但是序号值发生了变化!,所以在他们每出列一次要重新

    {

    for(i=1,k=0;i<=n;i++)//给士兵进行赋值操作!但是最后需要输出原来的数组编号!

    {

        if(a[i]%2==0&&b[i])//这并不难,因为标记数组的下标你又没有发生改变,所以到时候将数组b中对应是1的元素的下标输出来就行了!

        {

            b[i]=0;//把符合条件的赋值为0

            t--;

        }

        else if(b[i])//把不被整除的重新编号

        {

            k++;

            a[i]=k;

        }

       }

        if(t<=3)//t==n,人数小于3直接输出

          break;

    for(i=1,k=0;i<=n;i++)

    {

        if(a[i]%3==0&&b[i])

        {

            b[i]=0;

            t--;

        }

        else if(b[i])

        {

            k++;

            a[i]=k;

        }

    }

        if(t<=3)

            break;

    }

       for(i=1,j=0;i<=n;i++)//因为题上格式要求比较严格,所以我们要进行赋值到一个数组中,进行

       {

            if(b[i])//比较规格的输出!

               d[j++]=i;//ji1

       }

       if(t==3)

          printf("%d %d %d\n",d[0],d[1],d[2]);

       else if(t==2)

        printf("%d %d\n",d[0],d[1]);

       else if(t==1)

         printf("%d\n",d[0]);

    }

    return 0;

}

 



2017/7/17