♟️ 알고리즘/알고리즘_백준

[Python][백준] 1365. 꼬인 전깃줄 / LIS,이분탐색(G2)

Jerry_K 2025. 2. 13. 15:33

목차


    🖇️ 링크 

    https://www.acmicpc.net/problem/1365


    🗒️ 파이썬 코드 풀이

    from bisect  import bisect_left
    
    N = int(input())
    lst = list(map(int,input().split()))
    
    lis = [0]
    for i in range(len(lst)):
      if lis[-1] < lst[i]:
        lis.append(lst[i])
      else:
        v = bisect_left(lis,lst[i])
        lis[v] = lst[i]
    
    print(N-(len(lis)-1))

     

    1. 문제를 보고  LIS (Longest Increasing Sequence) 문제임을 알아야한다.

    처음 풀면, 생각할 수 없을 것 같다... 그냥 문제를 몇번 풀고 익숙해져야 될듯

     

    2. 문제의 조건은 전봇대의 개수 N(1 ≤ N ≤ 100,000) 이다.

    • 때문에 시간복잡도가 O(N^2) 이하여야 함
    • 이중 for 문이 안되기 떄문에, 이분탐색으로 접근

    3. 이제 조건에 맞게 lis 리스트를 오름차순으로 채워주면 된다.

    • lis 리스트의 가장 오른쪽에 있는 값이 가장 큰 값
    • 가장 오른쪽의 값보다  큰 경우
      • lis의 맨 앞 부분에 넣어줌 
    • 작거나 같은 경우 
      • 이분탐색으로 교체해줄 위치 찾고 교체

    📌  문제 코멘트 

     

    N = int(input())
    lst = list(map(int,input().split()))
    
    lis = [0]
    for i in range(len(lst)):
      if lis[-1] < lst[i]:
        lis.append(lst[i])
      else:
        for k in range(len(lis)-1):
          if lis[k] <= lst[i] < lis[k+1]:
            lis[k+1] = lst[i]
            break    
    
    print(N-(len(lis)-1))
    • 보통 LIS 알고리즘 방식이다. 
      • 이중 for문으로 LIS 문제를 해결한다.
      • 시간 복잡도는 O(N^2)으로 계산된다.
    • 이렇게하면 시간 초과가 발생한다.

     

    • 그래서 해당 문제는 O(NlogN)의 시간 복잡도를 가지게 이분 탐색을 한다.
    • 가장 헷갈렸던 부분은, 이렇게 막무가내로 값을 교체해도 되는지였다.
      • 길이 K의 증가 부분 수열은 K개의 위치가 항상 존재
      • 더 작은 값의 교체로 증가 수열의 원소 선택지를 넓혀줌

     

    문제의 로직만 알고 있으면, 구현자체는 막 어렵거나 하지 않다.


    📚문제

    공화국에 있는 유스타운 시에서는 길을 사이에 두고 전봇대가 아래와 같이 두 줄로 늘어서 있다. 그리고 길 왼편과 길 오른편의 전봇대는 하나의 전선으로 연결되어 있다. 어떤 전봇대도 두 개 이상의 다른 전봇대와 연결되어 있지는 않다.

    문제는 이 두 전봇대 사이에 있는 전깃줄이 매우 꼬여 있다는 점이다. 꼬여있는 전깃줄은 화재를 유발할 가능성이 있기 때문에 유스타운 시의 시장 임한수는 전격적으로 이 문제를 해결하기로 했다.

    임한수는 꼬여 있는 전깃줄 중 몇 개를 적절히 잘라 내어 이 문제를 해결하기로 했다. 하지만 이미 설치해 놓은 전선이 아깝기 때문에 잘라내는 전선을 최소로 하여 꼬여 있는 전선이 하나도 없게 만들려고 한다.

    유스타운 시의 시장 임한수를 도와 잘라내야 할 전선의 최소 개수를 구하는 프로그램을 작성하시오.

    입력

    첫 줄에 전봇대의 개수 N(1 ≤ N ≤ 100,000)이 주어지고, 이어서 N보다 작거나 같은 자연수가 N개 주어진다. i번째 줄에 입력되는 자연수는 길 왼쪽에 i번째 전봇대와 연결된 길 오른편의 전봇대가 몇 번 전봇대인지를 나타낸다.

     

    출력

    전선이 꼬이지 않으려면 최소 몇 개의 전선을 잘라내야 하는 지를 첫째 줄에 출력한다.

     

     

    예제 입력 1 복사

    4
    2 3 4 1
    

     

    예제 출력 1 복사

    1