力扣刷题之3148.矩阵的最大得分

题干描述

给你一个由 正整数 组成、大小为 m x n 的矩阵 grid。你可以从矩阵中的任一单元格移动到另一个位于正下方或正右侧的任意单元格(不必相邻)。从值为 c1 的单元格移动到值为 c2 的单元格的得分为 c2 - c1

你可以从任一 单元格开始,并且必须至少移动一次。

返回你能得到的 最大总得分。

示例 1:

**输入:**grid = \[9,5,7,3,8,9,6,1,6,7,14,3,2,5,3,1]

**输出:**9

解释: 从单元格 (0, 1) 开始,并执行以下移动:

  • 从单元格 (0, 1) 移动到 (2, 1),得分为 7 - 5 = 2

  • 从单元格 (2, 1) 移动到 (2, 2),得分为 14 - 7 = 7

总得分为 2 + 7 = 9

示例 2:

**输入:**grid = \[4,3,2,3,2,1]

输出:-1

解释: 从单元格 (0, 0) 开始,执行一次移动:从 (0, 0)(0, 1) 。得分为 3 - 4 = -1

题干分析

题干概述

你有一个正整数组成的矩阵grid,矩阵的大小mXn。你的任务是从矩阵的任意一个单元格开始移动,并且你只能往正下方或者正右侧移动。每次移动的得分是你到达的新单元格的值减去你原来所在单元格的值。你必须至少移动一次,然后计算你可以得到的最大总得分。

主要规则

1.移动方向
  • 你只能向右或者向下移动,也就是说,从一个位置到下一个位置必须在同一行或者同一列,且在同一行时必须往右,在同一列时必须往下。
2.得分计算
  • 每次移动的得分是从当前单元格的值c1到新单元格的值c2的差值,即c2 - c1。
3.起点和终点
  • 你可以从任意单元格开始,并且必须至少移动一次。
4.目标
  • 找到从某个起点开始,经过一系列合法移动之后,得到的最大总得分。

解题思路

1.定义状态
  • 用dpij表示从单元格(i,j)开始能够获得的最大总得分。
2.初始化
  • dp数组初始化为一个和grid大小相同的二维数组,初始值设置为负无穷大(INT_MIN),表示尚未计算过。
3.状态转移
  • dpij可以从以下两种情况种选择
  • 从下方单元格(i+1,j)移动到(i,j),此时得分为gridij - gridi+1j + dpi+1j.
  • 从右侧单元格(i,j+1)移动到(i, j),此时得分为gridij - gridij+1 + dpij+1.
  • 最终,dpij为上述两种选择中的最大值。
4.求解最终答案
  • 遍历整个dp数组,找到其中的最大值,即为所求的最大总得分。

代码实现

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

// 返回最大得分
int maxScore(int** grid, int gridSize, int* gridColSize) {
    int m = gridSize;
    int n = gridColSize[0];
    int dp[m][n];

    // 初始化dp数组
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            dp[i][j] = INT_MIN; // 初始值设为负无穷大
        }
    }

    int maxScore = INT_MIN;

    // 从右下到左上遍历
    for (int i = m - 1; i >= 0; i--) {
        for (int j = n - 1; j >= 0; j--) {
            // 当前单元格可以从右侧或下方转移过来
            if (i < m - 1) {
                dp[i][j] = grid[i + 1][j] - grid[i][j] + dp[i + 1][j];
            }
            if (j < n - 1) {
                dp[i][j] = grid[i][j + 1] - grid[i][j] + dp[i][j + 1];
            }

            // 如果dp[i][j]还是负无穷大,说明从该点开始没有合理的路径,所以不更新它

            // 更新最大得分
            if (i < m - 1 || j < n - 1) {
                maxScore = max(maxScore, dp[i][j]);
            }
        }
    }

    return maxScore;
}

// 主函数,用于测试
int main() {
    int grid1[4][4] = {
        {9, 5, 7, 3},
        {8, 9, 6, 1},
        {6, 7, 14, 3},
        {2, 5, 3, 1}
    };
    int grid2[2][3] = {
        {4, 3, 2},
        {3, 2, 1}
    };

    int* gridPointers1[4];
    int* gridPointers2[2];
    for (int i = 0; i < 4; i++) {
        gridPointers1[i] = grid1[i];
    }
    for (int i = 0; i < 2; i++) {
        gridPointers2[i] = grid2[i];
    }

    int gridColSize1[1] = {4};
    int gridColSize2[1] = {3};

    printf("Max score for grid1: %d\n", maxScore(gridPointers1, 4, gridColSize1));
    printf("Max score for grid2: %d\n", maxScore(gridPointers2, 2, gridColSize2));

    return 0;
}
相关推荐
To_OC2 小时前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
用户938515635077 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
To_OC8 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥9 小时前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程
地平线开发者10 小时前
Transformer模型部署之性能优化指南
算法
地平线开发者10 小时前
人在途中:从“编译失败”到“模型可落地”——CUDA 自定义算子
算法·自动驾驶
半个落月13 小时前
从递归到快速排序:用 JavaScript 把分治思想讲明白
javascript·算法·面试
小月土星14 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
javascript·算法·面试
小月土星14 小时前
JavaScript 递归入门:从 1 到 n 求和,再到数组扁平化
javascript·算法·面试