-
백준 2662번 : 기업투자알고리즘 공부 2020. 5. 2. 17:16
기업에 투자했을 때 보장된 이득을 볼 수 있다니! 이 얼마나 꿈같은 얘기인가~ 게다가 수익률도 기본적으로 100%가 넘는다...! 와! 샌즈! 와! 나도 할래 ㅠㅠ
풀이
만약 최대 이익만을 출력하는 문제였다면 조금 더 쉬웠을 것이다. 약간 응용된 배낭(냅색) 문제 정도? 하지만 각 기업에 투자한 액수를 출력하라는 문제 때문에 코드가 길어지고 구현이 조금 복잡해졌다. 일단 최대 금액을 구하는 것부터 해보자.
최대 금액 구하기
평소처럼 dp를 잘 정의하자.
dp[n][m] : n만원으로 1번 기업부터 m번 기업까지 투자할 때 얻을 수 있는 최대 이익
dp[n][m-1]인 상황에서 m번째 회사에 invest 만큼의 금액을 투자하면 dp [n + invest][m]이 된다.
dp [n + invest][m] = dp [n][m - 1] + menu [invest][m]
menu [invest][m] : invest원을 m번째 회사에 투자했을 때 얻는 이익
이때 투자 가능한 금액(invest)은 총 투자 금액 N을 넘을 수 없으므로 0 이상 N - n 이하일 것이다. 우리가 구하고자 하는 것은 최대 이익이므로 다른 루트로 온 값과 비교해서 큰 값을 채택해야 한다.
dp [n + invest][m] = max(dp [n + invest][m] , dp [n][m - 1] + menu [invest][m])
이런 방식으로 dp를 계산하면 dp [n][m]이 구하고자 하는 최대 이익이 될 것이다.
각 기업에 투자한 액수 구하기
문제는 여기다. 어떻게 각 기업에 투자한 금액을 구하지? 그 루트를 어떻게 추적하지? 나는 이 문제를 해결하기 위해 dp_invest라는 2차원 어레이를 하나 더 만들었다.
dp_invest [n][m] : dp [n][m]를 구할 때 최종적으로 결정된 m번째 회사의 투자 금액(invest)
정의가 좀 복잡하긴 한데 max함수를 통해 dp [n][m]에 어떤 값이 할당될 때 최종적으로 할당될 때의 invest 값을 저장해두는 것이다. 이를 위해 max함수를 쓰지 않고 if문을 통해 직접 비교하는 방식으로 바꿨다.
출력하기
출력은 stack을 사용했다. 최종 목적지는 dp [n][m]이라는 것은 알지만 거기까지의 도달 과정은 역추적할 수밖에 없는 상황이었기 때문에 LIFO(Last In First Out)인 stack을 사용하면 기록과 출력을 편하게 할 수 있을 것이라고 생각했기 때문이다.
dp_invest [n][m]의 값이 invest였다면 invest를 stack에 넣어둔다. 그다음 dp_invest [n-invest][m-1]을 stack에 넣는 과정을 반복한다.
#include <iostream> #include <stack> using namespace std; int n, m; int menu[302][21]; int dp[302][21]; int dp_invest[302][21]; stack<int> invests; int main() { cin >> n >> m; int trash; for(int i = 1; i <= n ; i++) { cin >> trash; for(int j = 1; j <= m; j++) { cin >> menu[i][j]; } } for(int comp = 1; comp <= m; comp++) { for(int value = 0; value <= n; value++) { for(int invest = 0; invest <= n-value; invest++) { if(dp[value+invest][comp] < dp[value][comp-1] + menu[invest][comp]) { dp[value+invest][comp] = dp[value][comp-1] + menu[invest][comp]; dp_invest[value+invest][comp] = invest; } } } } cout << dp[n][m] << "\n"; int invest; int value = n; int comp = m; while(comp != 0) { invest = dp_invest[value][comp]; invests.push(invest); value -= invest; comp -= 1; } while(invests.empty() == false) { cout << invests.top() << " "; invests.pop(); } return 0; }
'알고리즘 공부' 카테고리의 다른 글
백준 1720번 : 타일 코드 (1) 2020.05.04 백준 1695번 : 팰린드롬 만들기 (0) 2020.05.03 백준 1563번 : 개근상 (0) 2020.05.01 백준 2482번 : 색상환 (0) 2020.04.30 백준 2624 : 동전 바꿔주기 (0) 2020.04.28