https://www.acmicpc.net/problem/3114
(1, 1)에서 출발하여 (N, M)에 도착했을 때 사과 + 바나나의 최대를 구하는 문제입니다.
이동은 아래, 오른쪽, 오른쪽 + 아래 만 가능합니다.
(x, y) 기준 사과 + 바나나의 합은
1. (x, y) ~ (x - 1, y) 까지는 바나나
2. (x + 1, y) ~ (N, y) 까지는 사과
두개를 더하여 계산합니다.
그렇다면 사과와 바나나의 누적합은 각각 구할 수 있고, 세로별로 누적합을 구하도록 합니다.
세팅이 완료되었다면 점화식을 구해봅니다.
이동 가능한 방향이 어떻게 되는지를 이용하면 (x, y) 기준 3개 중 하나를 답으로 가져갈 수 있습니다.
(x - 1, y - 1), (x, y - 1)에서 왔을 경우 y 좌표가 바꼈으므로 이전에 구했던 누적합을 더하면 됩니다.
(x - 1, y)에서 왔을 경우 y좌표가 바뀌지 않았으므로 누적합 범위를 조정해야 합니다.
dp 값을 채워나가는 도중에 dp[N][M]보다 커지는 경우가 있을 수 있으니 dp[N][M]를 명시하여 출력해주시면 되겠습니다.
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
|
#include <iostream>
#include <algorithm>
#define MAX 1501
using namespace std;
int sumA[MAX][MAX], sumB[MAX][MAX], dp[MAX][MAX];
int N, M;
void func() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
if (j == 1) {
dp[i][j] = sumA[N][j] - sumA[i][j];
continue;
}
int tmp = sumA[N][j] - sumA[i][j] + sumB[i - 1][j];
dp[i][j] = max(max(dp[i - 1][j - 1], dp[i][j - 1]) + tmp, dp[i - 1][j] - sumA[i][j] + sumA[i - 1][j]);
}
}
cout << dp[N][M] << '\n';
}
void input() {
char ch;
int x;
cin >> N >> M;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
cin >> ch >> x;
if (ch == 'A') {
sumA[i][j] = x;
}
else {
sumB[i][j] = x;
}
sumA[i][j] += sumA[i - 1][j];
sumB[i][j] += sumB[i - 1][j];
}
}
}
int main() {
cin.tie(NULL); cout.tie(NULL);
ios::sync_with_stdio(false);
input();
func();
return 0;
}
|
cs |
'algorithm > dp' 카테고리의 다른 글
boj 2216 문자열과 점수 (0) | 2024.06.28 |
---|---|
boj 1354 무한 수열 2 (0) | 2024.06.27 |
boj 11560 다항식 게임 (0) | 2024.06.13 |
boj 28018 시간이 겹칠까? (0) | 2023.08.08 |
boj 12841 정보대 등산 (0) | 2023.07.31 |