1. 程式人生 > >CCF 學生排隊 (JAVA) -20170302

CCF 學生排隊 (JAVA) -20170302

問題描述

  體育老師小明要將自己班上的學生按順序排隊。他首先讓學生按學號從小到大的順序排成一排,學號小的排在前面,然後進行多次調整。一次調整小明可能讓一位同學出隊,向前或者向後移動一段距離後再插入佇列。
  例如,下面給出了一組移動的例子,例子中學生的人數為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,所有移動均合法。

思路

由題目中可以看出,需要頻繁地插入和刪除資料,所以程式碼使用LinkedList類來對插入和刪除元素的處理效率會高一點。程式碼中最核心的一點就是通過輸入所需要移動的學號與LinkedList類中的元素進行比較,如果兩者相等,則得到下標值進行下面的操作,然後先移除所需要移動的元素,最後在最終移動的位置中新增剛剛移除的元素。

程式碼

import java.util.LinkedList;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();//學生數量
		int m = scanner.nextInt();//調整的次數
		LinkedList<Integer>list = new LinkedList<Integer>();
		int[][] b = new int[m][2];//需要調整的學號以及移動的距離
		for(int i=0;i<m;i++){
			for(int j=0;j<2;j++){
				b[i][j]=scanner.nextInt();
			}
		}
		//初始化學生的學號
		for(int i=1;i<=n;i++){
			list.add(i);
		}
		int index=0;//索引
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				if(b[i][0]==list.get(j)){//得到當前位置i
					index=list.indexOf(list.get(j))+b[i][1];//移動的最終位置
					list.remove(list.get(j));//移除數值(先移除後新增)
					list.add(index,b[i][0]);//在需要的索引處新增剛剛移除的數值
					break;
				}
			}
		}
		for(int i=0;i<n;i++){
			System.out.print(list.get(i)+" ");
		}
	}

}