인프런 커뮤니티 질문&답변

백찬형님의 프로필 이미지
백찬형

작성한 질문수

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

5주차 개념 #3. 큰돌은 욕심많은 도서관 사서야!!!

그리디로 풀린다는 판단히 명확하게 서지 않습니다.

작성

·

106

0

31883번: FA수의 진 (acmicpc.net)

백준의 31883 문제를 DP로 풀면 깔끔하게 풀릴 수 있다고 생각해서 DP로 풀었습니다. 하지만 풀고나서 문제 카테고리가 그리디로 있는 걸 확인하고 그리디로 풀으니 더 코드가 깔끔하게 풀리는 경험을 했습니다.

 

그리디로 풀린다는 판단은 이 문제에서 어떻게 생각해야 되는 걸까요? 그리고 그리디 문제다 하는 판단 근거 유추를 어떻게 해야 하는지 강의에 있는 내용 외로 보충 설명 해주시면 감사하겠습니다.

 

아래는 DP로 풀은 코드 입니다.

import sys
input = sys.stdin.readline

N = int(input())
times = [list(map(int, input().split())) for _ in range(N)]
memo = [[0] * 2 for _ in range(N)]

memo[0][0] = times[0][0]
memo[0][1] = times[0][1]

for i in range(1, N):
    t1 = memo[i-1][0]
    tmp = t1 % (times[i][2] + times[i][3])
    if tmp >= times[i][2]:
        t1 += times[i][2] + times[i][3] - tmp
    t1 += times[i][0]

    t2 = memo[i-1][1]
    tmp = t2 % (times[i][2] + times[i][3])
    if tmp >= times[i][2]:
        t2 += times[i][2] + times[i][3] - tmp   
    t2 += times[i][0]

    cross1 = min(t1, t2)

    t3 = times[i][1] + memo[i-1][0]
    t4 = times[i][1] + memo[i-1][1]

    cross2 = min(t3, t4)

    memo[i][0] = cross1
    memo[i][1] = cross2

print(min(memo[N-1]))

답변 1

0

큰돌님의 프로필 이미지
큰돌
지식공유자

안녕하세요 찬형님 ㅎㅎ

먼저 강의 외의 문제 및 C++이외의 언어에 대한 답변은 드리지 않습니다.

 

다만 그리디에 대한 답변을 드리면요 ㅎㅎ

 

그리디로 풀린다는 판단은 이 문제에서 어떻게 생각해야 되는 걸까요? 그리고 그리디 문제다 하는 판단 근거 유추를 어떻게 해야 하는지 강의에 있는 내용 외로 보충 설명 해주시면 감사하겠습니다.

>> DP로 시도할 수 있나? -> 시간복잡도 및 공간복잡도를 고려함 -> 안될 것 같은데? -> 그리디를 시도해보자 라고 보시면 됩니다.

그리디는 매우 신중하게 접근해야 하는 알고리즘입니다. 어떤 명제를 만들고 그 명제가 참인지 거짓인지 모르는 상태로 그 명제를 바탕으로 코드를 짜는거라 반례가 있을 수 있는 확률도 많다는 것을 인지해야 합니다.

정확하게는 수학적 증명, 그리디 알고리즘이 항상 최적해를 보장하는지 증명(귀류법 등)을 하고 들어가야 하지만 이부분은 사실상 어렵기 때문에 앞서 제가 말씀드린 방법으로 판단해야 합니다.

 

감사합니다.

백찬형님의 프로필 이미지
백찬형

작성한 질문수

질문하기