Line Sweeping
Sweeping이라는 단어를 번역하면 "싹슬이 하는"이라는 뜻을 가집니다.
즉, "한 쪽 방향부터 시작해서 다른 방향으로 스캔해가면서 쓸어가는 것"입니다.
보통 라인스위핑 알고리즘은 좌표 문제에 많이 사용되며 O(nlogN)의 시간 복잡도를 가집니다.
라인 스위핑 알고리즘 문제 (백준 2170 : 선 긋기)
문제 설명
매우 큰 도화지에 자를 대고 선을 그으려고 한다.
매우 큰 도화지에 자를 대고 선을 그으려고 한다.
선을 그을 때에는 자의 한 점에서 다른 한 점까지 긋게 된다.
선을 그을 때에는 이미 선이 있는 위치에 겹쳐서 그릴 수도 있는데, 여러 번 그은 곳과 한 번 그은 곳의 차이를 구별할 수 없다고 하자.
이와 같은 식으로 선을 그었을 때, 그려진 선(들)의 총 길이를 구하는 프로그램을 작성하시오. 선이 여러 번 그려진 곳은 한 번씩만 계산한다.
입력
첫째 줄에 선을 그은 횟수 N(1 ≤ N ≤ 1,000,000)이 주어진다.
다음 N개의 줄에는 선을 그을 때 선택한 두 점의 위치 x, y(-1,000,000,000 ≤ x < y ≤ 1,000,000,000)가 주어진다.
출력
첫째 줄에 그은 선의 총 길이를 출력한다.
n | lines | result |
4 | [[1, 3], [2, 5], [3, 5], [6, 7] | 5 |
풀이
위의 입력값 대로 그림을 그려보면 다음과 같습니다.
result = 5가 어떻게 나오는지 봅시다.
파란색 선(1, 3)과 초록색 선(2, 5)를 비교했을 때 두 선이 겹치기 때문에 두 선을 합칠 수 있습니다. => 합친 선 (1, 5)
합친 선(1, 5)과 빨간 색(3, 5)를 비교합니다. 이 빨간색 선이 합친 선에 포함되기 때문에 변함이 없습니다.
합친 선(1, 5)와 보라색 선(6, 7)을 비교합니다. 이 두선은 서로 겹치거나 이어져 있지 않기 때문에 절대 합칠 수 가 없습니다.
그렇기 때문에 보라색 선의 길이를 따로 더해줘야합니다.
n = 4로 4개의 선을 다 탐색한 결과 합친 선(1, 5)와 보라색 선(6, 7) 남았습니다.
합친 선의 길이는 5 -1 = 4, 보라색 선의 길이는 7 - 6 = 1으로 두 선의 길이를 합치면 그은 선의 총 길이 = 5가 됩니다.
선 긋기 코드
package algorithm;
import java.util.Arrays;
public class LineSweeping {
public static void main(String[] args) {
int n = 4;
int[][] lines = new int[][]{{1, 3}, {2, 5}, {3, 5}, {6, 7}};
System.out.println(getLineLength(n, lines));
}
public static int getLineLength(int n, int[][] lines) {
// x좌표가 서로 같으면 y좌표 오름차순 정렬, 서로 다르면 x좌표 오름차순 정렬.
Arrays.sort(lines, (o1, o2) -> {
if (o1[0] == o2[0]) {
return o1[1] - o2[1];
} else {
return o1[0] - o2[0];
}
});
int prevX = lines[0][0]; // 이전 선의 x좌표
int prevY = lines[0][1]; // 이전 선의 y좌표
int len = prevY - prevX; // 현재 선의 길이
for (int i = 1; i < n; i++) {
int currentX = lines[i][0]; // 현재 선의 x좌표
int currentY = lines[i][1]; // 현재 선의 y좌표
/*
현재 선의 x가 이전 선의 x보다 크거나 같고,현재 선의 y가 이전 선의 y보다 크거나 작다면
현재 선이 이전 선에 포함되므로 다음 선으로 넘어간다.
*/
if (prevX <= currentX && currentY <= prevY) {
continue;
}
// 현재 선이 이전 선에 포함된다면, 두 선을 이어 붙인다.
if (currentX < prevY) {
len += currentY - prevY;
}
// 현재 선이 이전 선과 겹치지 않는다면, 겹치지 않는 선의 길이를 더한다.
if (currentX > prevY){
len += currentY - currentX;
}
// 이전 선을 현재 선으로 변경한다.
prevX = currentX;
prevY = currentY;
}
return len;
}
}
'◼ CS 기초 지식 > [알고리즘]' 카테고리의 다른 글
[알고리즘] 비트마스크(BitMask)란? (0) | 2023.02.04 |
---|---|
[알고리즘] 다익스트라(Dijkstra) - 최단거리 알고리즘 (0) | 2023.02.01 |
[알고리즘] 투 포인터(Two Pointers)란? (0) | 2023.01.27 |
[알고리즘] LIS(최장 증가 부분 수열)이란 ? (0) | 2023.01.26 |
[알고리즘] 힙 정렬(Heap Sort)이란? (0) | 2023.01.21 |