【ccf认证】201703-2 学生排队(c/c++)

试题编号: 201703-2
试题名称: 学生排队
时间限制: 1.0s
内存限制: 256.0MB
问题描述:

问题描述

  体育老师小明要将自己班上的学生按顺序排队。他首先让学生按学号从小到大的顺序排成一排,学号小的排在前面,然后进行多次调整。一次调整小明可能让一位同学出队,向前或者向后移动一段距离后再插入队列。
  例如,下面给出了一组移动的例子,例子中学生的人数为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,所有移动均合法。

基本思路:

1、由单链表实现。

2、移动时,获取该学生的编号num以及他要移至的位置index。如果是前移,则前插index,并删除num原来的数据;如果是后移,则后插index,并删除原来的数据。

3、注意不管是插入还是删除,如果位置为第1个,需要判断一下。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

struct node{
    int num;
    struct node *next;
};

typedef struct node LL;
typedef struct node *PLL;
PLL head;
int n,m;
int p,q;

void build(int n){
    PLL p,q;

    p = NULL;
    for(int i=1; i<=n; ++i){
        q = (PLL)malloc(sizeof(LL));
        q -> num = i;
        if( p== NULL ) head = q;
        else p -> next = q;
        p = q;
    }
    p -> next = NULL;
}

void display(){
    PLL p;
    p = head;
    while( p!=NULL ){
        printf("%d ",p->num);
        p = p -> next;
    }
    printf("\n");
}

PLL getElem(int index){
    int i=1;
    PLL p = head;
    while( i != index ){
        ++i;
        p = p-> next;
    }
    return p;
}

int getIndex(int num){
    PLL p;
    int index=1;
    p = head;
    while( p!=NULL ){
        if(p->num==num) return index;
        else{
            p = p -> next;
            index++;
        }
    }
}

//插入
void Insert(int index, int num, int q){
    PLL pp,s;

    if(index!=1){
        if(q<0) pp = getElem(index-1);
        if(q>0) pp = getElem(index);
    }else pp=head;
    if( pp == NULL ) return;

    s = (PLL)malloc(sizeof(LL));
    s -> num = num;
    if(index==1) {
        s->next=head;
        head = s;
    }
    else{
        s -> next = pp -> next;
        pp -> next = s;
    }
}

void delect(int index){
    if(index==1) head = head->next;
    else{
        PLL p,q;
        p = getElem(index-1);
        q = p -> next;
        p -> next = q-> next;
        free(q);
    }
}

void solve(int m){
    for(int i=0;i<m;i++){
        scanf("%d%d",&p,&q);
        if(q==0) continue;
        int index1=getIndex(p);
        int index2=index1+q;
        Insert(index2,p,q);
//        printf("index1=%d, index2=%d, insert:\n",index1,index2);
//        display();
        if(q>0) delect(index1);
        if(q<0) delect(index1+1);
//        printf("delete:\n");
//        display();
    }
}

int main(){
    scanf("%d%d",&n,&m);
    build(n);
    solve(m);
    display();

    return 0;
}

使用STL顺序容器list后的c++版本:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <list>

using namespace std;

int n,m,p,q;
list<int> l;
list<int>::iterator it1;
list<int>::iterator it2;

void init(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        l.push_back(i);
}

void display(){
    for(it2=l.begin();it2!=l.end();it2++)
        printf("%d ",*it2);
    printf("\n");
}

void solve(){
    for(int i=0;i<m;i++){
        scanf("%d%d",&p,&q);
        //迭代器指向p元素
        it1=find(l.begin(),l.end(),p);
        it2=it1;

        //注意insert使用的是前插法
        if(q>0)
            for(int j=0;j<=q;j++) it1++;
        if(q<0)
            for(int j=0;j<-q;j++) it1--;
        l.insert(it1,p);
        l.erase(it2);
        //display();
    }
}

int main(){

    init();
    solve();
    display();

    return 0;
}

需注意的是,insert采用的是前插法。

因此向后移位置时,定位点应该在目标位置的后一位,即 j=0; j<=q ;

而向前移位置时,定位点在目标位置,即 j=0; j<-q 。

发布了73 篇原创文章 · 获赞 55 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_35756383/article/details/88188256