在一个m x n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格,直到到达棋盘的右下角。请问你最多能拿到多少价值的礼物?
解题思路
这是一道基础的动态规划题,首先应该能想到用回溯法求解,然后再考虑是否能用动态规划来优化。
- 回溯法(会重复递归,复杂度较高)
- 动态规划(从上到下,循环计算,降低复杂度)
上代码(C++香)
法一:回溯法
long long maxVal = -1;
void dfs(int num[][4], int m, int n, int i, int j, int nowV){
if(i == m - 1 && j == n - 1){
if(nowV > maxVal)
maxVal = nowV;
return ;
}
if(j < n - 1)
// 向右走
dfs(num, m, n, i, j + 1, nowV + num[i][j + 1]);
if(i < m - 1)
// 向下走
dfs(num, m, n, i + 1, j, nowV + num[i + 1][j]);
}
法二:动态规划
int dp47(int num[][4], int rows, int cols){
int states[rows][cols];
memset(states, -1, sizeof(states));
states[0][0] = num[0][0];
// 初始化第一行第一列
for(int i = 1; i < rows; i++)
states[0][i] = states[0][i - 1] + num[0][i];
for(int i = 1; i < cols; i++)
states[i][0] = states[i - 1][0] + num[i][0];
// 填写每一行每一列
for(int i = 1; i < rows; i++)
for(int j = 1; j < cols; j++){
states[i][j] = num[i][j] + max(states[i - 1][j], states[i][j - 1]);
}
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++)
cout<<states[i][j]<<" ";
cout<<endl;
}
return states[rows - 1][cols - 1];
}