코딍코딍
코딩기록
코딍코딍
전체 방문자
오늘
어제
  • 분류 전체보기 (271)
    • 개발 (2)
    • Java (1)
    • 스프링 (28)
    • JPA (11)
    • Git (3)
    • 알고리즘 (160)
      • 백준 (132)
      • 프로그래머스 (8)
      • SWEA (20)
    • 토이 프로젝트 (14)
      • 간단한 Springboot CRUD (1)
      • 게시판 프로젝트 (13)
    • 알고리즘 개념정리 (8)
    • 오류 해결 (13)
    • 보류 (0)
    • AWS (5)
    • 트러블 슈팅 (0)
    • 회고 (3)
    • CS (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

최근 글

티스토리

hELLO · Designed By 정상우.
코딍코딍

코딩기록

알고리즘/백준

2170번 : 선 긋기

2023. 9. 10. 19:33

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

 

문제

매우 큰 도화지에 자를 대고 선을 그으려고 한다. 선을 그을 때에는 자의 한 점에서 다른 한 점까지 긋게 된다. 선을 그을 때에는 이미 선이 있는 위치에 겹쳐서 그릴 수도 있는데, 여러 번 그은 곳과 한 번 그은 곳의 차이를 구별할 수 없다고 하자.

이와 같은 식으로 선을 그었을 때, 그려진 선(들)의 총 길이를 구하는 프로그램을 작성하시오. 선이 여러 번 그려진 곳은 한 번씩만 계산한다.

 

입력

첫째 줄에 선을 그은 횟수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 다음 N개의 줄에는 선을 그을 때 선택한 두 점의 위치 x, y (-1,000,000,000 ≤ x < y ≤ 1,000,000,000)가 주어진다.

 

출력

첫째 줄에 그은 선의 총 길이를 출력한다.

 


소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int arr[][] = new int[n][2];
        for (int i = 0; i < n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            arr[i][0] = Integer.parseInt(st.nextToken());
            arr[i][1] = Integer.parseInt(st.nextToken());
        }

        // sorting
        Arrays.sort(arr, new Comparator<int[]> () {
            @Override
            public int compare(int[] o1, int[] o2) {
                if(o1[0] == o2[0]) {
                    return o1[1] - o2[1];
                } else return o1[0] - o2[0];
            }
        });

        long result = 0;
        int s = arr[0][0]; // 기존 선 시작점
        int e = arr[0][1]; // 기존 선 끝점
        for (int i = 1; i < n; i++) {
            int ns = arr[i][0]; // 현재 선 시작점
            int ne = arr[i][1]; // 현재 선 끝점
            
            // 연장
            if(s <= ns && ns <= e) {
                if(e < ne) e = ne;
            }
            // 포함
            else if(s <= ns && ne <= e) {
                continue;
            }
            // 새로운 선
            else {
                result += (Math.abs(e - s)); // 기존 선 길이 계산
                s = ns;
                e = ne;
            }
        }

        result += (Math.abs(e - s)); // 마지막 선 길이 계산
        System.out.println(result);
    }
}

 

해결방법

정렬 + 스위핑 알고리즘을 사용하여 문제를 해결했다.

문제는 의외로 간단하다. 먼저 시작점과 끝점 기준으로 정렬을 해준다. 그러면 시작점이 가장 작은 선부터 순서대로 배열에 정렬된다.

 

배열에 저장된 모든 선을 탐색하면서 아래 세 가지 경우만 판단하면 된다.

1) 선분이 새로 시작되는 경우

2) 선분이 연장되는 경우

3) 선분이 기존에 그렸던 선분에 완전히 포함되는 경우

 

세 가지 경우를 판단하여 코드를 구현하면 쉽게 해결할 수 있다. 

'알고리즘 > 백준' 카테고리의 다른 글

1744번 : 수 묶기  (0) 2023.09.12
11000번 : 강의실 배정  (0) 2023.09.11
9205번 : 맥주 마시면서 걸어가기  (0) 2023.09.08
1043번 : 거짓말  (0) 2023.09.08
6118번 : 숨바꼭질  (0) 2023.09.03
    '알고리즘/백준' 카테고리의 다른 글
    • 1744번 : 수 묶기
    • 11000번 : 강의실 배정
    • 9205번 : 맥주 마시면서 걸어가기
    • 1043번 : 거짓말
    코딍코딍
    코딍코딍
    ㅎ2

    티스토리툴바