[백준1114] 통나무 자르기

2021. 5. 3. 15:33·알고리즘 문제풀이

 

 

1114번: 통나무 자르기

첫째 줄에 L, K와 C가 주어진다. L은1,000,000,000보다 작거나 같은 자연수이고, K는 통나무를 자를 수 있는 위치의 개수이다. K와 C는 10,000보다 작거나 같은 자연수이다. 둘째 줄에 통나무를 자를 수

www.acmicpc.net

풀이

처음 생각(오답) :

제일 긴 토막이 짧도록 만드려면

나무토막중 제일 긴 토막을 우선적으로 잘라야 한다.

우선순위 큐를 이용해 제일 긴 토막을 차례대로 뽑아낸다.

우선순위 큐는 [나무길이,나무시작점,나무끝지점] 으로 저장한다.

길이를 최소로 만들어야 하기 때문에 나무의 최대한 중간에 있는 위치를 잘라야 한다.

이분탐색을 통해 나무범위에 해당하는 후보중 중간위치((나무시작점+나무끝지점) // 2)와 가까운 인덱스를 찾는다.

이것을 C번 반복하면서 최대길이 나무와 잘랐던 지점 중 최솟값을 찾는다.

틀린이유 :

1. 우선순위 큐에 남아있는 나무 중 가장 큰게 최대길이 나무인 줄 알았는데 아니었다.

2. 후보를 찾으려 할 때 나무길이범위안에 후보가 아예 없는 경우가 있다.

3. 중간위치에 가까운 인덱스 찾는게 어렵다.

4. 중간 지점을 찾아서 자른다고 해도 그게 처음 자르는 위치가 제일 작은 경우를 반환하지 않는다.

  • 10 3 2 / 1 2 5 가 주어졌을 때 지금 풀이대로라면 5를 선택하고 중간인 2를 선택한다. 그래서 답이 5,2가 출력된다.
  • 하지만 5를 선택하고 1을 선택해도 정답 조건을 만족한다. 따라서 답은 더 작은 수인 5 1 이 된다.

그러므로 틀렸다.

다음 생각(정답) :

이분탐색을 통해 푼다.

가장 긴 조각의 길이(x)를 하나씩 던져본다.

함수를 통해 긴 조각의 길이가 x가 맞는지 확인한다.

  • x를 고려해서 나무토막이 x보다 커지는 지점을 자른다. (후보군 간격이 x보다 작다면 자를 필요가 없고 x보다 크면 후보를 잘라야 최대길이가 x임을 만족한다.)
  • 결과적으로 자르는 횟수(cnt)가 c 보다 크다면 x를 키운다. ( cnt가 크다는 것은 결과적으로 나무를 많이 잘랐다는것. x가 커야 cnt가 줄어든다. 또한 c보다 크면 정답이 아니다. c이거나 이하여야 한다.)
  • 자르는 횟수가 c 이하라면 x를 줄인다. (여기서 정답이 나온다.)

여기서 더 생각해야 하는 부분 때문에 고생했다.

  • 뒤에서 부터 잘라서 처음 자르는 위치가 제일 작도록 한다.
  • 만약 cnt 가 C이하면 제일 왼쪽 후보를 추가적으로 자를 수 있다.
  • 자르는 위치의 간격이 x보다 크다면 x가 최대길이인게 불가능하므로 종료처리하고 x를 키운다.

시간복잡도

결과적으로 x를 통해 cnt값을 찾는 연산을 이분탐색 횟수만큼 진행한다.

연산은 후보군들(K개)를 for문에 돌리며 cnt를 찾는다.

이분탐색은 log(L) 의 시간복잡도를 가진다.

결과적으로 시간복잡도는 K * log(L) 가 된다.

코드

L,K,C = map(int,input().split())
cuts = [0,L] + list(map(int,input().split()))
cuts.sort()

def solution(x):
    cnt = 0
    cut_start = L
    prev=[]
    first = 0
    # x라는 길이를 넘으면 자른다.
    for i in range(len(cuts)-1,-1,-1):
        diff = cuts[i] - cuts[i-1]
        total = cut_start - cuts[i]
        if diff > x:
            return 10001,0
        elif total > x:
            cut_start = cuts[i+1]
            prev.append(cuts[i+1])
            cnt+=1
        else:
            continue

    if cnt < C:
        first = cuts[1]
    else:
        first = prev[-1]

    return cnt, first

lo = 0
hi = L
answer = 0
first_cut = 0
while lo <= hi:
    mid = (lo+hi)//2

    cnt,first = solution(mid)

    if C < cnt:
        lo = mid+1
    else:
        answer=mid
        first_cut = first
        hi = mid-1


print(answer,first_cut)

'알고리즘 문제풀이' 카테고리의 다른 글

[프로그래머스lv3] [2020 카카오 인턴십] 보석 쇼핑  (0) 2021.05.04
[프로그래머스lv.3] 순위  (0) 2021.05.04
[프로그래머스.lv3] 입국심사  (0) 2021.05.03
[백준2262] 토너먼트 만들기  (0) 2021.05.03
[백준1958] LCS 3  (0) 2021.05.03
'알고리즘 문제풀이' 카테고리의 다른 글
  • [프로그래머스lv.3] 순위
  • [프로그래머스.lv3] 입국심사
  • [백준2262] 토너먼트 만들기
  • [백준1958] LCS 3
WildDevmon
WildDevmon
『앗! 야생의 개발몬(이)가 나타났다!』
  • WildDevmon
    야생의 개발몬
    WildDevmon
  • 전체
    오늘
    어제
    • 분류 전체보기 (35)
      • Server (5)
      • 알고리즘 문제풀이 (27)
      • 회고 (3)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자바 스레드 상태
    카카오 필요스펙
    자바 최대공약수
    백준 어린 왕자
    소가 길을 건너간 이유 5
    백준6980
    백준 1114 파이썬
    1114백준
    경력 서류
    terminationGracePeriodSeconds
    백준1238
    백준 인형들
    다이렉트 버퍼
    백준 18405
    자바 물리 메모리
    백준 1004
    백준1188
    선발 명단
    백준 1114
    백준2262
    네이티브 메모리
    네카라쿠배 취업
    preStop
    graceful shutdown
    컴공 취준
    백준 고층 건물
    백준 10610
    백준 1034
    자바 프로세스 종료
    백준1747
    direct buffer
    자바 최소공배수
    백준 경쟁적 전염
    백준 17281
    파이썬
    ai개발자
    우아한 종료
    2020 카카오 인턴
    백준 파티
    백준 5347
    백준 1027
    백준15954
    백준 30
    백준 램프
    커널 스레드 상태
    백준14465
    통나무 자르기
    합승 택시 요금
    코틀린 코루틴
    소수&팰린드롬
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
WildDevmon
[백준1114] 통나무 자르기
상단으로

티스토리툴바