출처 : https://www.acmicpc.net/problem/11048
이동하기 성공
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
---|---|---|---|---|---|
1 초 | 256 MB | 9140 | 5180 | 3580 | 57.464% |
문제
준규는 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)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다.
예제 입력 1
3 4 1 2 3 4 0 0 0 5 9 8 7 6
예제 출력 1
31
예제 입력 2
3 3 1 0 0 0 1 0 0 0 1
예제 출력 2
3
예제 입력 3
4 3 1 2 3 6 5 4 7 8 9 12 11 10
예제 출력 3
47
출처
- 문제를 만든 사람: baekjoon
풀이
기본 dp를 이용하여 문제를 풀 수 있다.
처음에 1행과 1열을 초기화 한다.
그리고 나서 위, 왼쪽, 앞대각선의 값을 for문을 통해서 갱신해준다.
행렬을 그려놓고 생각하면 dp 의 행 순서대로 갱신하면서(2행부터 N행 까지) 모든 dp행렬을
2중 for문을 이용하여 갱신하는 것이다.
소스코드를 보면서 이해하면 더 쉽다.
! 팁 !
dp 를 top-down 을 이용하여 재귀함수를 쓰고 메모이제이션을 쓰는 경우에는 dp[][] 가 0이 아닐 때 리턴을 안해주면 시간 초과가 날 수 있다.
소스코드
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 | #include <iostream> #include <algorithm> #include <vector> using namespace std; int main(){ // init int N, M; scanf("%d %d", &N , &M); vector< vector<int> > num_mat(N+1, vector<int>(M+1, 0)); vector< vector<int> > dp_mat(N+1, vector<int>(M+1, 0)); for ( int n_idx = 1 ; n_idx <= N ; n_idx++) for ( int m_idx = 1 ; m_idx <= M ; m_idx++) scanf("%d", &(num_mat.at(n_idx).at(m_idx))); // dp 벡터 초기화 // 첫 행을 초기화 한다. for ( int m_idx = 1 ; m_idx <= M ; m_idx++) dp_mat.at(1).at(m_idx) += dp_mat.at(1).at(m_idx-1) + num_mat.at(1).at(m_idx); // 첫 열을 초기화 한다. for ( int n_idx = 2 ; n_idx <= N ; n_idx++) dp_mat.at(n_idx).at(1) = dp_mat.at(n_idx-1).at(1) + num_mat.at(n_idx).at(1); // dp를 수행한다. // 한 행씩 순차적으로 갱신한다. for ( int n_idx = 2 ; n_idx <= N ; n_idx++) for ( int m_idx = 2 ; m_idx <= M ; m_idx++) dp_mat.at(n_idx).at(m_idx) = num_mat.at(n_idx).at(m_idx) + max({ dp_mat.at(n_idx-1).at(m_idx) , dp_mat.at(n_idx).at(m_idx-1) , dp_mat.at(n_idx-1).at(m_idx-1) }); printf("%d", dp_mat.at(N).at(M) ); return 0; } | cs |