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문제라고 하는 것들을 백트레킹으로 재귀적으로 탐색하는 방법으로 풀었는데 점화식을 사용하여 좀 더 직관적으로 풀려서 재밌었다.

+ Recent posts