dp와 브루트포스 방식을 모두 적용할 수 있는 좋은 문제이다!
solve1은 브루트 포스와 dp를 적용해서 O(n^2)에 풀 수 있는 방법이다
solve2는 solve1과 논리는 같지만 top-down방식으로 재귀함수를 이용한 방법이다
solve3는 동적계획법을 최대한 활용해서 Pi, Ti를 뒤에서부터 탐색하는 방법을 사용해 O(N)만에 해결하는 방법이다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#include <iostream>
using namespace std;
int N, Ti[16], Pi[16], dp[16] = {0, };
void input(){
cin >> N;
for(int i = 0; i < N; i++){
cin >> Ti[i] >> Pi[i];
}
}
// O(N^2)
void solve1(){
int result = 0;
for(int i = 0; i < N; i++){
// Ti를 돌면서 Ti[i]와 i일을 더했을 때 N일 보다 크다면 일을 할 수 없으므로 넘어간다
if(Ti[i] + i > N) continue;
//처음 dp[i]에 접근하면 i일 일때 일한 수익으로 초기화
dp[i] = Pi[i];
// 처음부터 i일 직전까지 탐색
for(int j = 0; j < i; j++){
// j일 일때 그날의 일을 하고 마무리 하는 날이, i일을 넘어가면 i일의 일을 할 수 없으므로 넘어간다
if(j + Ti[j] > i) continue;
// 그렇지 않다면 현재 dp값과 (j일 까지 일한 최대 수익+i일 수익)중 큰값으로 dp값 교체
dp[i] = max(dp[i], Pi[i] + dp[j]);
}
// 결과 값 갱신
result = max(dp[i], result);
}
cout << result;
}
// top-down style O(N^2)
int solve2(int day){
if(day + Ti[day] > N) return 0;
if(day + Ti[day] == N) return Pi[day];
for(int i = day + Ti[day]; i <= N; i++){
dp[day] = max(dp[day], solve2(i) + Pi[day]);
}
return dp[day];
}
// dynamic programming bottom-up style O(N)
void solve3(){
int result = 0;
//뒤에서부터 탐색
for(int i = N-1; i >= 0; i--){
// next : 다음 날짜
int next = i + Ti[i];
if(next > N){
dp[i] = dp[i+1];
}
// next일에 일을 할지, 말지 결정
else{
dp[i] = max(dp[i+1], dp[next] + Pi[i]);
}
}
cout << dp[0];
}
int main(){
input();
int result = 0;
// for(int i = 0; i < N; i++){
// result = max(result, solve2(i));
// }
//
// cout << result;
solve3();
return 0;
}
|
cs |
algostudy 1주차문제
'Algorithm > BOJ' 카테고리의 다른 글
[백준 10090] Counting Inversion C++ (0) | 2021.04.19 |
---|---|
[백준 1111] IQ Test C++ (0) | 2021.04.19 |
[백준 2798] 블랙잭 C++ (0) | 2021.03.22 |
[백준 1074] Z C++ (0) | 2021.03.10 |
[백준 10830] 행렬 제곱 C++ (0) | 2021.03.10 |