试题编号: | 201703-2 |
试题名称: | 学生排队 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 体育老师小明要将自己班上的学生按顺序排队。他首先让学生按学号从小到大的顺序排成一排,学号小的排在前面,然后进行多次调整。一次调整小明可能让一位同学出队,向前或者向后移动一段距离后再插入队列。 输入格式 输入的第一行包含一个整数n,表示学生的数量,学生的学号由1到n编号。 输出格式 输出一行,包含n个整数,相邻两个整数之间由一个空格分隔,表示最终从前向后所有学生的学号。 样例输入 8 样例输出 1 2 4 3 5 8 6 7 评测用例规模与约定
扫描二维码关注公众号,回复:
9480673 查看本文章
对于所有评测用例,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 。