题目描述:
现在有一个8*8的棋盘,上面放着64个价值不等的礼物,每个小的棋盘上面放置一个礼物(礼物的价值大于0小于1000),一个人的初始位置在棋盘的左上角,每次他只能向下或向右移动一步,并拿走对应棋盘上的礼物,结束位置在棋盘的右下角,请设计一个算法使其能够获得最大价值的礼物。
思路
Leetcode 原题
dp[i][j] 表示 在第 (i,j) 个格子上能够获得的最大价值的礼物
状态转移方程为
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + matrix[i][j]
这题不应该再贴上, 不过上次做括号匹配没构造出状态转移方程, 那题与此题思路是类似的
状态方程的求解, 有时递推关系比较明显, 尤其是图, 树, 矩阵什么的, 但有时递推关系就比较隐晦, 比如括号匹配, 铺地板(编程之美)他们类似是因为他们有一个共同点, 即通向当前状态有几种选择. 当是括号时, 可以选择左括号或右括号, 是地板, 可以选择横着放或竖着放 , 当是树或图时, 可以选择是由那个分支
代码
#include <iostream> #include <stdio.h> using namespace std; int matrix[10][10]; int dp[10][10]; int dodp(int n) { for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j++) { int left = 0, up = 0; dp[i][j] = matrix[i][j]; if(j-1 >= 0) left = dp[i][j-1]; if(i-1 >= 0) up = dp[i-1][j]; dp[i][j] += max(left, up); } } return dp[n-1][n-1]; } int main() { //freopen("testcase.txt", "r", stdin); int n = 8; int first = 0; while(scanf("%d",&first) != EOF) { matrix[0][0] = first; for(int i = 1; i < n; i ++) scanf("%d", &matrix[0][i]); for(int i = 1; i < n; i ++) { for(int j = 0; j < n; j ++) { scanf("%d", &matrix[i][j]); } } int res = dodp(n); cout << res << endl; } return 0; }