작성
·
106
0
백준의 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로 시도할 수 있나? -> 시간복잡도 및 공간복잡도를 고려함 -> 안될 것 같은데? -> 그리디를 시도해보자 라고 보시면 됩니다.
그리디는 매우 신중하게 접근해야 하는 알고리즘입니다. 어떤 명제를 만들고 그 명제가 참인지 거짓인지 모르는 상태로 그 명제를 바탕으로 코드를 짜는거라 반례가 있을 수 있는 확률도 많다는 것을 인지해야 합니다.
정확하게는 수학적 증명, 그리디 알고리즘이 항상 최적해를 보장하는지 증명(귀류법 등)을 하고 들어가야 하지만 이부분은 사실상 어렵기 때문에 앞서 제가 말씀드린 방법으로 판단해야 합니다.
감사합니다.