面试题47:礼物的最大值

在一个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];
}
posted @ 2020-08-20 12:57  程序员曾奈斯  阅读(159)  评论(0编辑  收藏  举报