Algorithm
백준 2170번 <선 긋기>
seungh2
2023. 11. 20. 23:52
백준 알고리즘 2170번
https://www.acmicpc.net/problem/2170
2170번: 선 긋기
첫째 줄에 선을 그은 횟수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 다음 N개의 줄에는 선을 그을 때 선택한 두 점의 위치 x, y (-1,000,000,000 ≤ x < y ≤ 1,000,000,000)가 주어진다.
www.acmicpc.net
2170번
매우 큰 도화지에 자를 대고 선을 그으려고 한다. 선을 그을 때에는 자의 한 점에서 다른 한 점까지 긋게 된다. 선을 그을 때에는 이미 선이 있는 위치에 겹쳐서 그릴 수도 있는데, 여러 번 그은 곳과 한 번 그은 곳의 차이를 구별할 수 없다고 하자.
이와 같은 식으로 선을 그었을 때, 그려진 선(들)의 총 길이를 구하는 프로그램을 작성하시오. 선이 여러 번 그려진 곳은 한 번씩만 계산한다.
문제 해결
그리디 알고리즘으로 해결했다.
문제를 푸는 로직을 찾는 건 어렵지 않았는데 시간초과를 해결하는데 시간을 좀 썼다.
선이 여러 번 그려질 수 있다는 것이 문제에 명시되어 있기 때문에 중복을 빼고 계산을 해주어야 시간초과가 나지 않는다.
문제를 해결하는 로직은 다음과 같다.
- 선을 긋는 시작 지점을 기준으로 오름차순 정렬을 진행한다.
- start에 1번째 선의 start를, end에 1번째 선의 end를 저장한다.
- 그 다음 나머지 선들을 순서대로 보며 다음과 같은 프로세스를 수행한다.
- 만약 현재 선의 start가 end보다 작거나 같으면 겹치는 선이기 때문에 end의 값을 현재 선의 end 중 큰 값으로 업데이트한다.
- 만약 현재 선의 start가 end보다 크다면 겹치지 않기 때문에 지금까지 그어진 선의 길이(end-start)를 누적시킨다. 그 다음에 start에 현재 선의 start를, end에 현재 선의 end를 저장한다.
- 마지막에 그어진 선의 길이(end-start)를 누적시킨다.
시간초과를 피하기 위해 시작 지점이 같은데 끝 지점이 다른 경우를 걸러주기 위해 HashMap을 사용해 key에 시작지점을, value에 끝 지점 중 가장 큰 값을 저장하여 중복을 없애주었다.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
public class BOJ_2170 {
static class Tuple{
int start, end;
public Tuple(int start, int end) {
this.start = start;
this.end = end;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < N; i++) {
String[] inArr = br.readLine().split(" ");
int a = Integer.parseInt(inArr[0]);
int b = Integer.parseInt(inArr[1]);
int temp = map.getOrDefault(a, a);
map.put(a, Math.max(temp, b));
}
ArrayList<Tuple> line = new ArrayList<>();
for (Integer key : map.keySet()) {
int temp = map.get(key);
line.add(new Tuple(key, temp));
}
Collections.sort(line, (a, b) -> Integer.compare(a.start, b.start));
int start = line.get(0).start;
int end = line.get(0).end;
int acc = 0;
for (int i = 1; i < line.size(); i++) {
if (end >= line.get(i).start) { // 겹침
end = Math.max(line.get(i).end, end);
} else { // 안겹침
acc += (end - start);
start = line.get(i).start;
end = line.get(i).end;
}
}
acc += (end - start);
System.out.println(acc);
}
}
결과
728x90