문제: icpc.me/5721
최대로 가져갈 수 있는 사탕의 수를 구하는 문제이다.
동적 계획법으로 문제를 해결 가능하다.
dp[x][y][z] = x-1행 까지 모든 사탕상자와 x행의 y행 까지의 사탕상자를 커버했을 때 가질 수 있는 최대 사탕 개수
(이 때 z는 x행에서 사탕상자를 한번이라도 커버했는 지 여부이다)
이렇게 정의를 해주면 dp[x][y][z]= max(a[x][y]+ dp[x][y+2][1], dp[x][y+1][z]) 라는 대략적인 점화식이 세워진다.
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 | #include <cstdio> #include <algorithm> #include <vector> using namespace std; vector<vector<int>> a; vector<vector<vector<int>>> dp; int n, m; int func(int x, int y, int z) { if (x > n - 1) return 0; int &ret = dp[x][y][z]; if (ret != -1)return ret; if (y >= m - 1) { if (x == n - 1) { if (y == m - 1) return ret = a[x][y]; else return ret = 0; } if (y == m - 1) { if (z) return ret = a[x][y] + func(x + 2, 0, 0); else return ret = max(a[x][y] + func(x + 2, 0, 0), func(x + 1, 0, 0)); } if (z) return ret = func(x + 2, 0, 0); else return ret = func(x + 1, 0, 0); } return ret = max(a[x][y] + func(x, y + 2, 1), func(x, y + 1, z)); } int main() { while (scanf("%d%d", &n, &m) != EOF) { if (!n&&!m)break; a.assign(n, vector<int>(m, 0)); dp.assign(n + 1, vector<vector<int>>(m + 1, vector<int>(2, -1))); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf("%d", &a[i][j]); } } printf("%d\n", func(0, 0, 0)); } return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)1063 킹 (0) | 2017.08.02 |
---|---|
BOJ)1514 자물쇠 (0) | 2017.08.01 |
BOJ)11560 다항식 게임 (0) | 2017.08.01 |
BOJ)10276 Jewelry Exhibition (0) | 2017.08.01 |
BOJ)1999 최대최소 (0) | 2017.07.31 |