[BOJ] 2565. 전깃줄

LIS (최장 증가 수열)

  • 메모리 : 13,132 KB
  • 시간 : 72 ms
  • 코드길이 : 2,113 B
  • 소요시간 : 1H
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main_B_2565_전깃줄 {

	static class Line {
		int start;
		int dest;

		public Line(int start, int dest) {
			this.start = start;
			this.dest = dest;
		}

	}

	static int N;
	static Line[] line;

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		N = Integer.parseInt(in.readLine());
		line = new Line[N];
		int[] temp = new int[N]; // LIS로 사용 가능한 숫자를 저장할 배열
		int[] path = new int[N]; // 경로를 저장할 배열, 역추적할 index를 저장
		int size = 0; // LIS 개수를 관리할 변수
		int A, B;

		for (int n = 0; n < N; n++) {
			st = new StringTokenizer(in.readLine(), " ");
			A = Integer.parseInt(st.nextToken());
			B = Integer.parseInt(st.nextToken());
			line[n] = new Line(A, B);
		} // end input

		// 도착지를 기준으로 정렬
		Arrays.sort(line, new Comparator<Line>() {

			@Override
			public int compare(Line o1, Line o2) {
				return o1.dest - o2.dest;
			}

		});

		path[size] = -1; // 첫번째 숫자라는 의미
		temp[size++] = 0; // 첫번째 숫자의 index 반영
		for (int i = 1; i < N; i++) {
			if (line[temp[size - 1]].start < line[i].start) {
				path[i] = temp[size - 1];
				temp[size++] = i;
			} else {
				int tmp = binarySearch(temp, 0, size, line[i].start);
				if (tmp < 0)
					tmp = -tmp - 1;
				path[i] = path[temp[tmp]];
				temp[tmp] = i;
			}
		}

		System.out.println(N - size);
	} // end main

	private static int binarySearch(int[] temp, int fromIndex, int toIndex, int key) {
		int low = fromIndex;
		int high = toIndex - 1;

		while (low <= high) {
			int mid = (low + high) >>> 1;
			int midVal = line[temp[mid]].start;

			if (midVal < key)
				low = mid + 1;
			else if (midVal > key)
				high = mid - 1;
			else
				return mid; // key found
		}
		return -(low + 1); // key not found.
	}

}

재귀를 이용한 완탐

  • 시간초과가 뜨긴 하지만 재귀를 이제 완전히 이해하는 것 같아서 기록해 놓는다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main_B_2565_전깃줄 {

	static class Line {
		int start;
		int dest;

		public Line(int start, int dest) {
			this.start = start;
			this.dest = dest;
		}

	}

	static int N, min;
	static Line[] line;

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		N = Integer.parseInt(in.readLine());
		min = Integer.MAX_VALUE;
		line = new Line[N];

		int A, B;

		for (int n = 0; n < N; n++) {
			st = new StringTokenizer(in.readLine(), " ");
			A = Integer.parseInt(st.nextToken());
			B = Integer.parseInt(st.nextToken());
			line[n] = new Line(A, B);
		} // end input

		Arrays.sort(line, new Comparator<Line>() {

			@Override
			public int compare(Line o1, Line o2) {
				return o1.dest - o2.dest;
			}

		});

		recursive(0, 0, 0);

		System.out.println(min);
	} // end main

	private static void recursive(int index, int before, int flag) {
		if (index == N - 1) {
			int cnt = 0;
			for (int n = 0; n < N; n++) {
				if ((flag & (1 << n)) == 0) {
					cnt++;
				}
			}
			min = Math.min(min, cnt);
			return;
		}

		for (int n = index; n < N; n++) {
			if ((flag & (1 << n)) == 0) {
				if (line[n].start >= line[before].start)
					recursive(n, index, (flag | (1 << n)));
			}
		}
	}
}

Leave a comment