

처절했던 사투에 비해 코드는 간결하구나..
문제가 많았다.
1. 점화식 제대로 못 찾음.
2. 문제 자체를 정확하게 이해하지 못했음
3. 내가 짠 코드를 내가 이해하지 못함
문제 설명부터 시작해서 차근차근 다시 이해해보자
| 1일 | 2일 | 3일 | 4일 | 5일 | 6일 | 7일 | |
| $T_i$ | 3 | 5 | 1 | 1 | 2 | 4 | 2 |
| $P_i$ | 10 | 20 | 10 | 20 | 15 | 40 | 200 |
| $dp[i]$ | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1일에 상담을 했다면, 2 3일에는 상담을 할 수 없다. 그러므로 $1+T_i$인 4, 즉 dp[4]에는 1일차 $P_i$인 10이 들어간다
| 1일 | 2일 | 3일 | 4일 | 5일 | 6일 | 7일 | |
| $T_i$ | 3 | 5 | 1 | 1 | 2 | 4 | 2 |
| $P_i$ | 10 | 20 | 10 | 20 | 15 | 40 | 200 |
| $dp[i]$ | 0 | 0 | 0 | 10 | 0 | 0 | 0 |
1일에 하지 않고 2일에 상담을 했다면,
3 4 5 6일에 상담을 할 수 없으므로, 7일에 2일차 $P_i$인 20이 들어간다
| 1일 | 2일 | 3일 | 4일 | 5일 | 6일 | 7일 | |
| $T_i$ | 3 | 5 | 1 | 1 | 2 | 4 | 2 |
| $P_i$ | 10 | 20 | 10 | 20 | 15 | 40 | 200 |
| $dp[i]$ | 0 | 0 | 0 | 10 | 0 | 0 | 20 |
1, 2일을 건너뛰고 3일에 상담을 했다면,
4일에도 바로 상담을 할 수 있고, 10이 들어간다. 그런데 이미 10이 들어가 있으므로, 최댓값을 계산할 땐 의미가 없다. 문제에서 총 얼마를 받는 지가 궁금했던 거지, 언제언제 상담을 할 수 있는 지가 궁금한 것은 아니다.
| 1일 | 2일 | 3일 | 4일 | 5일 | 6일 | 7일 | |
| $T_i$ | 3 | 5 | 1 | 1 | 2 | 4 | 2 |
| $P_i$ | 10 | 20 | 10 | 20 | 15 | 40 | 200 |
| $dp[i]$ | 0 | 0 | 0 | 10 | 0 | 0 | 20 |
암튼 4일까지의 최대로 받는 돈은 10이다. 4일에 상담을 진행한다면, 5일의 dp[i]에 $dp[i]+T_i =10+20=30$이 들어가게 된다
| 1일 | 2일 | 3일 | 4일 | 5일 | 6일 | 7일 | |
| $T_i$ | 3 | 5 | 1 | 1 | 2 | 4 | 2 |
| $P_i$ | 10 | 20 | 10 | 20 | 15 | 40 | 200 |
| $dp[i]$ | 0 | 0 | 0 | 10 | 30 | 0 | max(20,45) |
5일에 상담을 받으면, 6일에 받지 못한다.
그렇다면 7일에 받을 수 있는 돈은 15+30=45인데, dp[7]에는 이미 20이 들어가 있다. 여기서 비교를 해야 한다.
dp[i+T[i]] = max(dp[i+T[i]], dp[i]+P[i])
이미 들어가 있는 값과, 새로 만들어진 값 중 더 큰 값을 저장한다!!
| 1일 | 2일 | 3일 | 4일 | 5일 | 6일 | 7일 | |
| $T_i$ | 3 | 5 | 1 | 1 | 2 | 4 | 2 |
| $P_i$ | 10 | 20 | 10 | 20 | 15 | 40 | 200 |
| $dp[i]$ | 0 | 0 | 0 | 10 | 30 | 0 | 45 |
6일과 7일에 상담을 받으면, 퇴사기준일을 넘어가버린다.. 반복에선 포함하는 범위지만, 데드라인을 넘어가서 값을 갱신하
지 않는다.
전체 코드
#include <algorithm>
#include <cmath> //C++
#include <iostream>
#include <math.h> //C
#include <queue>
#include <string>
#include <vector>
int *T;
int *P;
int *dp;
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n;
cin >> n;
T = new int[n + 7];
P = new int[n + 7];
dp = new int[n + 7];
fill(dp, dp + (n + 7), 0);
for (int i = 1; i <= n; i++) {
cin >> T[i] >> P[i];
}
int maxi=0;
//n+1일째에 상담이 끝나도 안 돼
for (int i = 1; i <= n+1; i++) {
//cout << "maxi : " << maxi << " " << "dp[i] :" << dp[i] << '\n';
dp[i] = max(maxi, dp[i]);
//cout << "maxi now : " << maxi << '\n';
if (i + T[i] <= n+1) {
//cout << "오늘 : " << i << " 다음 상담 시작일 : " << i + T[i] << '\n';
//cout << "비교대상 : " << dp[i+T[i]] << " " << P[i] + dp[i] << '\n';
dp[i + T[i]] = max(dp[i + T[i]], P[i] + dp[i]);
//cout << i+T[i] << "일의 최대 상담금액 : " << dp[i + T[i]] << '\n';
//이미 들어가 있는 최대랑, 들어갈 최대를 비교 : i일까지의 상담액의 최대
}
//if(i==n && T[i]==1){dp[i+1] += P[i];}
//cout << "갱신 전 maxi : " << maxi << " " << "dp[" << i+T[i] <<"]:" << dp[i+T[i]] << '\n';
maxi = max(maxi, dp[i]);
//cout << "갱신 후 maxi : " << maxi << " " << "dp[" << i+T[i] <<"]:" << dp[i+T[i]] << '\n';
}
cout << maxi << '\n';
delete[] T;
delete[] P;
delete[] dp;
return 0;
}
$i+T[i] <= n+1$인 이유는, 위에서 설명했다 시피 n일에 m일짜리 상담을 잡으면 그 금액이 n+m일에 기록되기 때문이다
dp[i] = max(maxi, dp[i]);
이 코드를 작성해야 할 것을 몰라서 몇 시간을 헤맸는데, 무슨뜻이냐?
지금 자리에, 지금까지 상담액의 최대를 기록한다는 뜻이다.
= 오늘 기준으로 끝나는 상담이 없다고 dp[i]를 0으로 두는 것이 아니라, 이전까지의 최대를 기록해 둔다는 것이다. 유남쌩
Intellectual Honesty
'공부기록 > [Algorithm]' 카테고리의 다른 글
| 백준 2579번 <계단 오르기> - C++ (2) | 2024.08.29 |
|---|---|
| 백준 15829번 <Hashing> - C++ (3) | 2024.08.24 |
| 백준 10816번 <숫자 카드 2> -C++ (0) | 2024.08.23 |
| 백준 1018번 <체스판 다시 칠하기> - C++ (3) | 2024.08.20 |
| 백준 11650번 <좌표 정렬하기> - C++ (0) | 2024.08.17 |