한 개의 회의실이 있는데 이를 사용하고자 하는 N개의 회의들에 대하여 회의실 사용표를 만들려고 한다. 각 회의 I에 대해 시작시간과 끝나는 시간이 주어져 있고, 각 회의가 겹치지 않게 하면서 회의실을 사용할 수 있는 최대수의 회의를 찾아라. 단, 회의는 한번 시작하면 중간에 중단될 수 없으며 한 회의가 끝나는 것과 동시에 다음 회의가 시작될 수 있다. 회의의 시작시간과 끝나는 시간이 같을 수도 있다. 이 경우에는 시작하자마자 끝나는 것으로 생각하면 된다.


문제 출처: https://www.acmicpc.net


코드

import java.util.Scanner;

public class Main {
	
	public int[][] sort(int[][] inputList) {
		if(inputList.length<2)
			return inputList;
		else {
			return merge(sort(split(inputList).firstList),sort(split(inputList).secondList));
		}
	}
		
	class ListTuple{
		int[][] firstList;
		int[][] secondList;
		
		public ListTuple(int[][] list1, int[][] list2) {
			firstList=list1;
			secondList=list2;
		}
	}
	
	public ListTuple split(int[][] list) {
		int lengthOfInput=list.length;
		int i=0; //counter
		int[][] list1=new int[lengthOfInput/2][2], list2=new int[lengthOfInput-lengthOfInput/2][2];
		for(int[] temp:list) {
			if(i<(int)(lengthOfInput/2))
				list1[i]=temp;
			else
				list2[i-lengthOfInput/2]=temp;
			i++;
		}
		return new ListTuple(list1, list2);
	}
	
	public int[][] merge(int[][] list1, int[][] list2) {
		int length=list1.length+list2.length;
		int[][] result=new int[length][2];
		for(int i=0, j=0;i+j<length;){
			if(i==list1.length) {
				for(;j<list2.length;){
					result[i+j]=list2[j];
					j++;
				}
				break;
			}
			if(j==list2.length) {
				for(;i<list1.length;) {
					result[i+j]=list1[i];
					i++;
				}
				break;
			}
			
			if(list1[i][1]<list2[j][1] || (list1[i][1]==list2[j][1] && list1[i][0]<list2[j][0])) {
				result[i+j]=list1[i];
				i++;
			}
			else {
				result[i+j]=list2[j];
				j++;
			}
		}
		return result;
	}
		
	public int[][] merge(ListTuple tuple) {
		return merge(tuple.firstList,tuple.secondList);
	}
	
	public static void main(String[] args) {
		Main main=new Main();
		Scanner sc=new Scanner(System.in);
		int N=sc.nextInt();

		int[][] time=new int[N][2];
		int availableTime=0, count=0;
		for(int i=0;i<N;i++) {
			time[i][0]=sc.nextInt();
			time[i][1]=sc.nextInt();
		}
//		for(int i=0;i<N;i++) {
//			time[i][0]=(int)(150*Math.random());
//			time[i][1]=time[i][0]+(int)(150*Math.random());
//			System.out.printf("%d %d,  ",time[i][0],time[i][1]);
//			if(i%10==9)
//				System.out.println();
//		}														
//		long start=System.currentTimeMillis();
		time=main.sort(time);
		for(int i=0;i<N;i++) {
//			System.out.printf("%d %d,  ",time[i][0],time[i][1]);
//			if(i%10==9)
//				System.out.println(); 
			if(availableTime<=time[i][0]) {
				availableTime=time[i][1];
				count++;
			}
		}
		System.out.println(count);

//		System.out.println((System.currentTimeMillis()-start)/1000.0);
	}
}

처음에 문제를 풀 때 끝나는 시간을 기준으로 정렬한 후에, 가능한 회의 중 가장 빨리 끝나는 회의에 회의실을 배정하는 식으로 배치했다.

그렇게 했을 때 답이 다르게 나왔는데, 시작시간을 기준으로 정렬하는 것을 하지 않아서 그랬던 것. 다른 경우는 가능한 회의 수에 영향을 주지 않지만, 시작과 동시에 끝나는 회의가 있는 경우 그 회의는 끝나는 시간이 같은 회의 중 맨 마지막에 위치해 있어야 회의 수를 최대로 할 수 있다.

따라서 시작하자마자 끝나는 회의를 맨 뒤로 밀어도 되고, 아니면 끝나는 시간이 같은 회의들은 시작시간을 기준으로 정렬되도록 해 주면 된다. 나는 시작시간을 기준으로도 정렬되도록 수정.

주석처리한 부분은 실행시간을 확인하기 위한 부분과, 랜덤한 데이터를 집어넣기 위한 부분, 그리고 정렬이 제대로 이루어졌는지 확인하기 위한 부분 등이 있다. 문제를 풀 때 자주 삽입하는 편.

'Exercises' 카테고리의 다른 글

백준 14502  (0) 2018.05.06
백준 프로그래밍 9343  (0) 2018.05.06
백준 문제 11729  (0) 2018.05.01
백준 프로그래밍: GCD  (0) 2018.04.23
기초: Merge Sort  (0) 2018.04.23

+ Recent posts