1. 程式人生 > >csp 201703-2 學生排隊

csp 201703-2 學生排隊

  • 題目

問題描述

  體育老師小明要將自己班上的學生按順序排隊。他首先讓學生按學號從小到大的順序排成一排,學號小的排在前面,然後進行多次調整。一次調整小明可能讓一位同學出隊,向前或者向後移動一段距離後再插入佇列。   例如,下面給出了一組移動的例子,例子中學生的人數為8人。   0)初始佇列中學生的學號依次為1, 2, 3, 4, 5, 6, 7, 8;   1)第一次調整,命令為“3號同學向後移動2”,表示3號同學出隊,向後移動2名同學的距離,再插入到佇列中,新佇列中學生的學號依次為1, 2, 4, 5, 3, 6, 7, 8;   2)第二次調整,命令為“8號同學向前移動3”,表示8號同學出隊,向前移動3名同學的距離,再插入到佇列中,新佇列中學生的學號依次為1, 2, 4, 5, 8, 3, 6, 7;   3)第三次調整,命令為“3號同學向前移動2”,表示3號同學出隊,向前移動2名同學的距離,再插入到佇列中,新佇列中學生的學號依次為1, 2, 4, 3, 5, 8, 6, 7。   小明記錄了所有調整的過程,請問,最終從前向後所有學生的學號依次是多少?   請特別注意,上述移動過程中所涉及的號碼指的是學號,而不是在隊伍中的位置。在向後移動時,移動的距離不超過對應同學後面的人數,如果向後移動的距離正好等於對應同學後面的人數則該同學會移動到佇列的最後面。在向前移動時,移動的距離不超過對應同學前面的人數,如果向前移動的距離正好等於對應同學前面的人數則該同學會移動到佇列的最前面。

輸入格式

  輸入的第一行包含一個整數n,表示學生的數量,學生的學號由1到n編號。   第二行包含一個整數m,表示調整的次數。   接下來m行,每行兩個整數p, q,如果q為正,表示學號為p的同學向後移動q,如果q為負,表示學號為p的同學向前移動-q。

輸出格式

  輸出一行,包含n個整數,相鄰兩個整數之間由一個空格分隔,表示最終從前向後所有學生的學號。

樣例輸入

8 3 3 2 8 -3 3 -2

樣例輸出

1 2 4 3 5 8 6 7

評測用例規模與約定

  對於所有評測用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 1000,所有移動均合法。

  • 基本思路

這題其實也還好,就是陣列位置之間的操作,這個首先要找學號的位置,因為肯定不是最初的了,變化多次之後就肯定不是學號第幾就是第幾位置了。如果是向後移動的話,那麼這個學號的位置的下一位的位置要賦值過去,依次進行,直到移動q次,然後q次之後剩下的那個位置就是這個學號的位置了。如果是向前移動的話,那麼這個學號的位置的前一位就要賦值過來,依次進行,直到移動q次,然後q次之後剩下的位置就是這個學號的位置了。

  • 演算法思想

初始化學號的位置,然後每次要進行移動先找這個學號的位置,從這個學號的位置進行操作,如果是向前移動的話,那麼他的前一位要賦值到他的位置,依次進行,如果是向後移動的話,那麼他的後一位要賦值到他的位置,依次進行。多次操作之後就是最後的所有學號的位置了。

  • 流程
  1. 讀入資料
  2. 初始化學號位置的陣列
  3. 看q是大於0還是小於0
  4. 大於0向後移動的陣列進行操作
  5. 小於0向前移動的陣列進行操作
  6. 多次移動之後輸出最後的位置
  • 程式碼實現

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

const int maxn=1009;

int a[maxn];

int main(){

    int n,m,p,q;

    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;++i){///先初始化每個位置

        a[i]=i;

    }

    while(m--){

        scanf("%d%d",&p,&q);///讀入資料

        int pos;

        for(int i=1;i<=n;++i){

            if(a[i]==p){///先找這個學號的位置

                pos=i;

                break;

            }

        }

        if(q>0){

            int t=a[pos];

            for(int i=pos;i<pos+q;++i){///從這個學號的位置開始移動,因為這個學號的位置要出隊,那麼他的下一個位置肯定要補充過去

                a[i]=a[i+1];

            }

            a[pos+q]=t;///都補充好之後,移動的位置之後剩的那個位置就是這個學號的

        }else{

            int t=a[pos];///類似的,一個是向前移動。一個是向後移動

            for(int i=pos;i>pos+q;--i){

                a[i]=a[i-1];

            }

            a[pos+q]=t;

        }

    }

    for(int i=1;i<=n;++i){///輸出

        printf("%d ",a[i]);

    }

    return 0;

}