https://www.acmicpc.net/problem/11048
11048번: 이동하기
준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다. 준규는
www.acmicpc.net
문제
준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다.
준규는 현재 (1, 1)에 있고, (N, M)으로 이동하려고 한다. 준규가 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 이동할 수 있고, 각 방을 방문할 때마다 방에 놓여져있는 사탕을 모두 가져갈 수 있다. 또, 미로 밖으로 나갈 수는 없다.
준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수의 최댓값을 구하시오.
입력
첫째 줄에 미로의 크기 N, M이 주어진다. (1 ≤ N, M ≤ 1,000)
둘째 줄부터 N개 줄에는 총 M개의 숫자가 주어지며, r번째 줄의 c번째 수는 (r, c)에 놓여져 있는 사탕의 개수이다. 사탕의 개수는 0보다 크거나 같고, 100보다 작거나 같다.
출력
첫째 줄에 준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다.
접근방법 및 풀이
- 점화식을 구해 dp로 풀 수 있다.
- i,j번째 값은 i-1,j / i,j-1 / i-1,j-1번째 dp배열값중 최대값 + i,j번째 칸의 사탕개수 이다.
- 첫번째 열과 첫번째 행에 대해 구간합을 구해서 초기 dp배열을 세팅해준다.
#include <iostream>
#include <algorithm>
#define VMAX 1001
using namespace std;
int main(){
int n,m; cin >> n >> m;
int s[VMAX][VMAX]={0};
int d[VMAX][VMAX]={0};
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
scanf("%d", &s[i][j]);
if(i==1 || j==1) d[i][j] = s[i][j];
}
}
for(int i=1; i<=n; i++){
d[i][1]+=d[i-1][1];
}
for(int j=1; j<=m; j++){
d[1][j]+=d[1][j-1];
}
for(int i=2; i<=n; i++){
for(int j=2; j<=m; j++){
d[i][j] = max({d[i][j-1], d[i-1][j], d[i-1][j-1]}) + s[i][j];
}
}
printf("%d", d[n][m]);
}
느낀점
처음에는, 소위 dp문제라고 하는 것들을 백트레킹으로 재귀적으로 탐색하는 방법으로 풀었는데 점화식을 사용하여 좀 더 직관적으로 풀려서 재밌었다.
'알고리즘 문제풀이' 카테고리의 다른 글
[백준] 1922번 네트워크 연결 c++ (0) | 2021.08.11 |
---|---|
[백준] 1600번 말이 되고픈 원숭이 c++ (0) | 2021.08.09 |
[백준] 2573번 빙산 c++ (0) | 2021.08.06 |
[백준] 5014번 스타트링크 c++ (0) | 2021.08.05 |
[백준] 2468번 안전 영역 c++ (0) | 2021.08.05 |