Toolofv 님의 블로그

[Python] 백준 - 2565 전깃줄 본문

Algorithm

[Python] 백준 - 2565 전깃줄

Toolofv 2024. 10. 15. 17:49

 

 

백준 - 2565 전깃줄

첫째 줄에는 두 전봇대 사이의 전깃줄의 개수가 주어진다. 전깃줄의 개수는 100 이하의 자연수이다. 둘째 줄부터 한 줄에 하나씩 전깃줄이 A전봇대와 연결되는 위치의 번호와 B전봇대와 연결되는 위치의 번호가 차례로 주어진다. 위치의 번호는 500 이하의 자연수이고, 같은 위치에 두 개 이상의 전깃줄이 연결될 수 없다.

www.acmicpc.net

문제

두 전봇대 A와 B 사이에 하나 둘씩 전깃줄을 추가하다 보니 전깃줄이 서로 교차하는 경우가 발생하였다. 합선의 위험이 있어 이들 중 몇 개의 전깃줄을 없애 전깃줄이 교차하지 않도록 만들려고 한다.

예를 들어, < 그림 1 >과 같이 전깃줄이 연결되어 있는 경우 A의 1번 위치와 B의 8번 위치를 잇는 전깃줄, A의 3번 위치와 B의 9번 위치를 잇는 전깃줄, A의 4번 위치와 B의 1번 위치를 잇는 전깃줄을 없애면 남아있는 모든 전깃줄이 서로 교차하지 않게 된다.

< 그림 1 >

 

전깃줄이 전봇대에 연결되는 위치는 전봇대 위에서부터 차례대로 번호가 매겨진다. 전깃줄의 개수와 전깃줄들이 두 전봇대에 연결되는 위치의 번호가 주어질 때, 남아있는 모든 전깃줄이 서로 교차하지 않게 하기 위해 없애야 하는 전깃줄의 최소 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에는 두 전봇대 사이의 전깃줄의 개수가 주어진다. 전깃줄의 개수는 100 이하의 자연수이다. 둘째 줄부터 한 줄에 하나씩 전깃줄이 A전봇대와 연결되는 위치의 번호와 B전봇대와 연결되는 위치의 번호가 차례로 주어진다. 위치의 번호는 500 이하의 자연수이고, 같은 위치에 두 개 이상의 전깃줄이 연결될 수 없다.

출력

 

첫째 줄에 남아있는 모든 전깃줄이 서로 교차하지 않게 하기 위해 없애야 하는 전깃줄의 최소 개수를 출력한다.

 

필요한 도구

 

 

1. DP = [1 x 전봇대 개수] 

2. sort 알고리즘

 

문제해결방법

 

 

1. "시작 전봇대""끝 전봇대"가 있다고 하자. "시작 전봇대"는 n개이고, "끝 전봇대"는 각 "시작 전봇대"에서 연결된 전봇대다.

2. 각 "시작 전봇대"를 돌면서 유효한 전봇대를 구해보자. (먼저 내림차순으로 정렬하여 큰 번호부터 돌자. 1번부터 돌자.)

 

1) 어떤 "시작 전봇대"와 연결된 "끝 전봇대"의 번호가 그 앞의 "시작 전봇대"들의 연결된 "끝 전봇대"보다 작아야 교차하지 않는다. 반대로 말하면 앞의 있는 "시작 전봇대"에 연결된 "끝 전봇대"는 커야만 유효하다.

2) 각 "시작 전봇대"와 연결된 "끝 전봇대"가 유효한 경우를 DP에 넣어본다.

 

for i in range(1, n):   # 1    2    3    4    5     6      7
    for j in range(i):  # 0    01   012  0123 01234 012345 0123456

 

a. 포커싱된 "시작 전봇대"( i )로 그 앞의 "시작 전봇대"( j )를 돌려면 저런 형태의 2중 for문이 필요하다. 자주 활용가능하다.

 

if d[i][1] < d[j][1]:
   dp[i] = max(dp[j]+1, dp[i])

 

b. 포커싱된 "시작 전봇대" ( i )에서 연결된 "끝 전봇대" 값(d[ i ][ 1 ])보다 그 전 "시작 전봇대"( j )에 연결된 각 "끝 전봇대"값(d[ j ][ 1 ])이 클 때 유효한 것이다. 유효한 전봇대의 경우 먼저 구해놓은 값(dp[ j ])에 + 1(자신 포함) 해준다. ( i 와 가까운  j - 전봇대가 엉켜있는 경우 앞의 전봇대가 뒤의 전봇대의 값보다 작을 수도 있다.)

 

 

 

3. DP가 전부 구성되면 각 시작 전봇대가 자기 자신을 포함하여 유효한 경우의 전봇대를 연결한 값을 갖고 있다.

 

1) 그 DP값의 최댓값을 전체 전봇대 개수에서 빼주면 없애야 하는 전봇대의 최소값이 된다.

 

- 코드

import sys
input = sys.stdin.readline

n = int(input())
d = [list(map(int, input().split())) for _ in range(n)]
d.sort(key = lambda x : -x[0])
dp = [1 for _ in range(n)]
cnt = 0

for i in range(1, n):
    for j in range(i):
        if d[i][1] < d[j][1]:
            dp[i] = max(dp[j]+1, dp[i])
print(n-max(dp))
반응형