n이 최대 15이기 때문에 최악의 경우에도 2^15가지의 경우의 수를 가진다. 따라서 완전탐색을 해도 문제가 없다. 하지만 동적 계획법으로도 해결할 수 있기 때문에 두가지 방법을 다뤄보겠다.
먼저 깊이우선탐색을 이용한 방법이다. (이전 금액을 가져와 최종적으로 비교해야 하기 때문에 dfs를 사용한다.) 현재 day에서 선택 할지 안 할지를 재귀적으로 호출한다. 결과적으로 최종 money를 비교해 ans에 저장한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include<iostream> usingnamespacestd; int n, ans, t[16], p[16]; voiddfs(int day, int money){ if(day > n + 1) return; if(day == n + 1) { if(ans < money) ans = money; return; } dfs(day + t[day], money + p[day]); dfs(day + 1, money); } intmain(){ cin >> n; for(int i = 1; i <= n; i++) cin >> t[i] >> p[i]; dfs(1, 0); cout << ans; }
동적 계획법을 이용한 방법이다. dp[i + t]값 보다 dp[i] + p값이 크다면 dp[i + t]에 dp[i] + p를 넣는다. 내일까지 벌 수 있는 최대 금액보다 오늘 벌 수 있는 최대 금액이 더 크다면 내일도 오늘만큼 벌 수 있으므로 dp[i + 1] = dp[i] 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13
#include<iostream> #include<algorithm> usingnamespacestd; int n, t, p, dp[16]; intmain(){ cin >> n; for(int i = 0; i < n; i++) { cin >> t >> p; dp[i + t] = max(dp[i + t], dp[i] + p); dp[i + 1] = max(dp[i + 1], dp[i]); } cout << dp[n]; }