https://jaimemin.tistory.com/2181 글을 참고하였습니다.
알고력 alp와 코딩력 cop에 도달하는 최단 시간을 dp[alp][cop]로 하는 2차원 배열을 만듭니다. 문제에서는 모든 문제를 다 풀수 있는 알고력과 코딩력에 도달하라고 합니다. 그래서 모든 문제를 순회하면서 alp_max와 cop_max을 고릅니다. 어떤 문제를 풀어가면서 최소한의 시간을 쓸 수 있을까요? 이건 알고력과 코딩력이 나눠진 상태에서 여러 문제를 풀어서 alp_max와 cop_max 지점에 가는 것입니다.
초기의 알고력 을 나타내는 alp 와 초기의 코딩력을 나타내는 cop가 주어지는데 이 범위는 0이상 150이하입니다. 동적계획법을 풀때는 그 목표가 동적이라는 걸 인지할 필요가 있습니다. 그 말인즉슨, 어떤 상태(dp[i][j])가 의미하는게 그 값이 서로 다른 경우의 조합으로 만들어진다는 말입니다.
이 문제에서는 상태가 알고력과 코딩력이고, 각각의 능력치가 달라서 (dp[i][j] 의 업데이트 되는 조건이 따로 있음) 그렇게 됩니다. 표를 그려서 설명해보면 다음과 같습니다. 표의 크기는 임의로 정했습니다.
1. 문제가 없는 상황이다. 지금 알고력 코딩력은 0, 0 이다.
| 0 | 1 | 2 | 3 | 4 | 5 |
| 1 | 2 | 3 | 4 | 5 | 6 |
| 2 | 3 | 4 | 5 | 6 | 7 |
| 3 | 4 | 5 | 6 | 7 | 8 |
| 4 | 5 | 6 | 7 | 8 | 9 |
2. 현재의 알고력 및 코딩력이 0, 0 일때, 1문제([1, 1, 1, 1, 1])가 추가된다면 각 위치에서의 소요시간은 아래와 같이 변한다.
| 0 | 1 | 2 | 3 | 4 | 5 |
| 1 | 2 | 3 | 4 | 5 | 6 |
| 2 | 3 | 3 | 4 | 5 | 6 |
| 3 | 4 | 4 | 4 | 5 | 6 |
| 4 | 5 | 5 | 5 | 5 | 6 |
3. 현재의 알고력 및 코딩력이 0, 0일때, 1문제가 더 추가된다면(총 [1, 1, 1, 1, 1], [4, 5, 2, 1, 1]) 각 위치에서의 소요시간은 아래와 같이 변한다. 밑줄 친 값이 우리가 원하는 목표 알고력, 코딩력에 도달하는 시간이다.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 2 | 3 | 3 | 4 | 5 | 6 | 7 |
| 3 | 4 | 4 | 4 | 5 | 6 | 7 |
| 4 | 5 | 5 | 5 | 5 | 6 | 7 |
| 5 | 6 | 6 | 6 | 6 | 6 | 7 |
4. 3문제([1, 1, 1, 1, 1], [4, 5, 2, 1, 1], [2, 2, 1, 2, 1])가 있다고 생각해보자. 밑줄 친 숫자부터 새로운 문제를 풀어 알고력과 코딩력을 늘릴수 있다면 물음표가 붙은 숫자들을 최소값으로 업데이트 할수 있을까? 아래에 최소로 업데이트 할수 있는 숫자들을 표시해두었다. 최소시간으로 업데이트가 가능한지 생각해보자.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 2 | 3 | 3 | 4 | 5 | 6 | 7 |
| 3 | 4 | 4 | 4 | 5? | 6? | 7? |
| 4 | 5 | 5 | 5 | 5? | 6? | 7? |
| 5 | 6 | 6 | 6 | 6? | 6? | 7? |
이는 아래처럼 업데이트 될 수 있다.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 2 | 3 | 3 | 4 | 5 | 6 | 7 |
| 3 | 4 | 4 | 4 | 4 | 6 | 7 |
| 4 | 5 | 5 | 5 | 5 | 5 | 5 |
| 5 | 6 | 6 | 6 | 6 | 6 | 6 |
그러면 이제 확장시켜봐야할때,
그럼 이제 2차원 배열을 채운 아이디어를 그대로 이용할 수 있다.
import sys
sys.setrecursionlimit(int(1e8))
def dfs(algo, coding, problems):
if algo >= alp_max and coding >= cop_max:
return 0
if dp[algo][coding] != -1:
return dp[algo][coding]
dp[algo][coding] = 987654321
dp[algo][coding] = min(dp[algo][coding], dfs(min(alp_max, algo+1), coding, problems) + 1)
dp[algo][coding] = min(dp[algo][coding], dfs(algo, min(cop_max, coding+1), problems) + 1)
for i in range(len(problems)):
if problems[i][0] > algo or problems[i][1] > coding:
continue
dp[algo][coding] = min(dp[algo][coding], dfs(min(alp_max, algo+problems[i][2]), min(cop_max, coding+problems[i][3]), problems) + problems[i][4])
return dp[algo][coding]
def solution(alp, cop, problems):
global dp, alp_max, cop_max
answer = 0
alp_max, cop_max = 0, 0
for i in range(len(problems)):
alp_req, cop_req = problems[i][0], problems[i][1]
if alp_max < alp_req:
alp_max = alp_req
if cop_max < cop_req:
cop_max = cop_req
bnd_alp, bnd_cop = 160, 160
dp = [[-1]*(bnd_alp) for _ in range(bnd_cop)]
answer = dfs(alp, cop, problems)
return answer| [743] Network Delay Time (LeetCode) (0) | 2022.09.23 |
|---|---|
| [10986] 나머지 합 (백준) (0) | 2022.09.23 |
| [7579] 앱 (백준) (0) | 2022.09.03 |
| [1541] 잃어버린 괄호 (백준) (0) | 2022.07.10 |
| [1325] 효율적인 해킹 (백준) (0) | 2022.07.06 |
댓글 영역