백준 2662번 기업투자
문제풀이
사용한 알고리즘 : DP
(1) 코드 7~8
'dp[x][k] : 1이상~x이하 기업에 k원을 투자하여 얻을 수 있는 최대 이익' 이라고 설정했습니다.
최종 얻는 최대 이익은 dp[M][N] 일 것입니다.
(2) 코드 9~11
최대 이익을 얻기 위해 각 기업에서 얼만큼 투자를 했는지 추적하는 배열입니다.
'path[x][k] : dp[x][k]를 최대로 만들 때, x기업에 투자하는 금액' 이라고 설정하였습니다.
input:
3 3
1 5 2 3
2 6 5 7
3 7 9 8
인 예를 들어보면 다음과 같이 생각할 수 있습니다.
투자금액 \ 기업 |
1 |
2 |
3 |
1 |
5 |
2 |
3 |
2 |
6 |
5 |
7 |
3 |
7 |
9 |
8 |
DP와 이에따른 path 표를 짜보면 다음과 같습니다.
금액 \ 기업 |
1 |
2 |
3 |
|||
dp |
path |
dp |
path |
dp |
path |
|
1 |
5 |
1 |
5 |
0 |
5 |
0 |
2 |
6 |
2 |
7 |
1 |
8 |
1 |
3 |
7 |
3 |
10 |
2 |
12 |
2 |
예를 들어 ,
dp[3][3] = 12
= 기업 1에 1을 투자해 5 얻음 + 기업 3에 2를 투자해 7 얻음
입니다.
따라서 path[3][3] = 2
= 1~3기업에서 3원으로 최대 이익을 얻을 때 3기업에 투자한 금액은 2
입니다.
(3) 코드 22~36
과정(2)의 생각에 따라 모든 기업, 투자 금액에 따른 dp값과 path값을 구합니다.
(4) 코드 38
구하고자 하는 답은 'dp[M][N] : 1~M 기업에서 N 금액으로 얻는 최대 이익' 입니다.
(4) 코드 39~51
최대 이익을 얻기 위해 각 기업에 투자한 금액을 각각 구해줍니다.
탐색은 N기업에서 역으로 진행됩니다.
각 탐색시, dp값을 구하기 위해 현재 기업에 투자한 금액을 구한 뒤,
이를 총 투자금액에서 빼주면서 탐색을 진행합니다.
위의 예를 들면,
dp[3][3] = 12 이고, path[3][3] = 2 입니다.
즉 3 기업에 투자한 금액은 2 입니다.
따라서 다음 탐색에서는 dp[2][3-2] 를 생각합니다.
dp[2][1] = 5 이고, path[2][1] = 0 입니다.
즉 2 기업에 투자한 금액은 0 입니다.
마지막 탐색에서는 dp[1][1-0] 을 생각하겠죠?
dp[1][1] = 5 이고, path[1][1] = 1 입니다.
즉 1 기업에 투자한 금액은 1 입니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
int N, M; | |
// company[x][k] : x 회사에 k원 투자할 때 얻는 가치 | |
int company[22][333]; | |
// dp[x][k] : x 까지 회사에서 k원으로 얻을 수 있는 최대 가치 | |
int dp[22][333]; | |
// 각 기업 투자 액수 추적할 배열 | |
// path[x][k] : dp[x][k]를 최대로 만드는 x에서 투자한 금액 | |
int path[22][333]; | |
int main() {ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> N >> M; | |
for (int i = 1; i <= N; ++i) { | |
int invest; | |
cin >> invest; | |
for (int i = 1; i <= M; ++i) cin >> company[i][invest]; | |
} | |
for (int i = 1; i <= M; ++i) { // 모든 기업 | |
for (int cost = 1; cost <= N; ++cost) { // 모든 투자 금액 | |
// i 기업에서 j만큼 쓴다고 생각. | |
for (int j = 0; j <= cost; ++j) { | |
// 이전 dp[i-1][cost-j] 에서 얻은 이익 + i기업에서 j금액으로 얻은 이익 | |
int val = dp[i - 1][cost - j] + company[i][j]; | |
if (val > dp[i][cost]) { // 이게 더 이득이면 | |
// dp 값 최신화 | |
dp[i][cost] = val; | |
// dp[i][cost] 값을 최대로 만드는 i번째 회사 투자금액 | |
path[i][cost] = j; | |
} | |
} | |
} | |
} | |
cout << dp[M][N] << '\n'; | |
vector<int> ans; | |
int curr = M; | |
int cost = N; | |
while (curr > 0) { | |
// dp[curr][cost] 를 최대로 만드는 현재 기업에서 투자하는 금액 | |
int now_invest = path[curr][cost]; | |
ans.push_back(now_invest); | |
// 현재 기업에서 투자한 만큼 빼줌 | |
cost -= now_invest; | |
// 이전 기업 | |
curr--; | |
} | |
reverse(ans.begin(), ans.end()); | |
for (auto it : ans) cout << it << ' '; | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!