Today's special moments become memories of tomorrow.

BOJ

[백준 3020번] 개똥벌레 (java)

lotus lee 2021. 3. 30. 20:23

 

3020번: 개똥벌레

개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이

www.acmicpc.net

 

누적합으로 문제를 해결하였다.

 

각각의 높이에 따라 석순과 종유석의 개수를 카운트하는 두 개의 배열 bot, top을 생성하였다.

 

예를 들어, 첫 번째 구간에서는 석순이 7개 존재하므로 bot[1] = 7 이 된다.

두 번째 구간에는 석순이 6개 존재하므로 bot[2] = 6 

세 번째 구간에는 석순이 5개 존재하므로 bot[3] = 5 

네 번째 구간에는 석순이 1개 존재하므로 bot[4] = 1 

다섯 번째 구간에는 석순이 0개 존재하므로 bot[5] = 0 

 

첫 번째 구간에는 종유석이 0개 존재하므로 top[1] = 0

두 번째 구간에는 종유석이 2개 존재하므로 top[2] = 2

세 번째 구간에는 종유석이 5개 존재하므로 top[3] = 5

네 번째 구간에는 종유석이 7개 존재하므로 top[4] = 7

다섯 번째 구간에는 종유석이 7개 존재하므로 top[5] = 7

		for (int i = 0; i < N / 2; i++) {
			bot[Integer.parseInt(br.readLine())]++;
			top[H - Integer.parseInt(br.readLine()) + 1]++;
		}

 

그 다음, 구해진 bot과 top 배열을 이용하여 누적합(Prefix Sum)을 구한다.

누적합을 이용하면 O(n)의 시간복잡도가 걸린다.

		for (int i = 1; i <= H; i++) {
			bot[i] += bot[i - 1];
		}

		for (int i = H; i >= 1; i--) {
			top[i] += top[i + 1];
		}

 

누적합을 구한 후, 첫 번째 구간부터 H번째 구간까지 차례대로 장애물의 수를 확인한 다음, min과 cnt을 갱신해준다.

 

i번째 구간에서의 석순의 개수는 bot[H] - bot[i-1]

i번째 구간에서의 종유석의 개수는 top[H] - top[i+1] 로 구할 수 있다.

이 두 결과를 더한 값이 i번째 구간에서의 장애물의 총 개수가 된다.

int obs = (bot[H] - bot[i - 1]) + (top[1] - top[i + 1]);

		int min = N;
		int cnt = 0;

		for (int i = 1; i <= H; i++) {
			int obs = (bot[H] - bot[i - 1]) + (top[1] - top[i + 1]);

			if (obs < min) {
				min = obs;
				cnt = 1;
			} else if (obs == min)
				cnt++;
		}

 

전체 코드 :