【多维DP】力扣3122. 使矩阵满足条件的最少操作次数

给你一个大小为 m x n 的二维矩形 grid 。每次 操作 中,你可以将 任一 格子的值修改为 任意 非负整数。完成所有操作后,你需要确保每个格子 gridij 的值满足:

如果下面相邻格子存在的话,它们的值相等,也就是 gridij == gridi + 1j(如果存在)。

如果右边相邻格子存在的话,它们的值不相等,也就是 gridij != gridij + 1(如果存在)。

请你返回需要的 最少 操作数目。

示例 1:

输入:grid = \[1,0,2,1,0,2]

输出:0

解释:

矩阵中所有格子已经满足要求。

示例 2:

输入:grid = \[1,1,1,0,0,0]

输出:3

解释:

将矩阵变成 \[1,0,1,1,0,1] ,它满足所有要求,需要 3 次操作:

将 grid10 变为 1 。

将 grid01 变为 0 。

将 grid12 变为 1 。

示例 3:

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

输出:2

解释:

这个矩阵只有一列,我们可以通过 2 次操作将所有格子里的值变为 1 。

提示:

1 <= n, m <= 1000

0 <= gridij <= 9

二维DP

cpp 复制代码
class Solution {
public:
    int minimumOperations(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(n, vector<int>(10, 1e9));

        //初始化第一列
        for(int k = 0; k <= 9; k++){
            int cost = 0;
            for(int i = 0; i < m; i++){
                cost += (grid[i][0] != k);
            }
            dp[0][k] = cost;
        }

        for(int j = 1; j < n; j++){
            vector<int> new_dp(10, 1e9);
            for(int k = 0; k <= 9; k++){    //当前列的值为k
                int cost = 0;
                for(int i = 0; i < m; i++){
                    cost += (grid[i][j] != k);
                }

                for(int u = 0; u <= 9; u++){    //上一列的值为u
                    if(u != k){
                        new_dp[k] = min(new_dp[k], dp[j-1][u] + cost);
                    }
                }
            }
            dp[j] = move(new_dp);
        }

        int ans = 1e9;
        for(int k = 0; k <= 9; k++){
            ans = min(ans, dp[n-1][k]);
        }
        return ans;
    }
};

这道题我们可以定义一个二维的数组dpjv的含义是第j列第一个格子为v时的最小代价。

首先我们要初始化第一列的值,我们假设第一列的值可能是0~9之间任何一个值k,然后grid第一列中不等于k则要修改成k,所以有多少个不等于k的值就要操作多少次,记录到cost中,最后dp0k = cost。

接下来到代码核心部分,先遍历每一列j,然后我们定义一个数组new_dpk来表示该列的值为k的最小操作次数是多少。我们先记录cost也就是如果第j列值为k的话第j列要操作几次,然后我们再假设上一列的值u,只有当上一列的值u不等于当前列的值k的时候,当前列才能从上一列进行状态转移而来,对应方程new_dp[k] = min(new_dp[k], dp[j-1][u] + cost);。最后new_dpk会根据上一列的不同u来计算出最小的new_dpk,最后我们只需要将new_dp的值对应到dpj中即可。

最后我们定义一个变量ans来记录前n-1列(从0开始索引)并且最后一列不同数时的总最小操作次数,最后返回ans即可。

相关推荐
零依赖极客5 小时前
Day 6·1 ARMv8.2 dotprod——vdotq_s32 一条指令做 4 个点积
c语言·开发语言·人工智能·矩阵·arm·vllm
stolentime5 小时前
洛谷P10515 转圈题解
c++·算法·数学建模·贪心算法
和裕7 小时前
蜂窝板 vs 七层瓦楞重型纸箱:大件工业设备运输性能与成本全对比
大数据·运维·网络·人工智能·算法
衡石科技7 小时前
Data_Agent记忆机制与经验复用衡石分析智能体会话记忆与长期学习技术解析
人工智能·科技·学习·算法·企业级bi
wzdark8 小时前
基于矩阵的动态规划路径问题性能优化4
线性代数·矩阵·动态规划
shirsl8 小时前
算法 Day 2 滑动窗口 + 栈 / 单调栈
开发语言·python·算法
土司大王9 小时前
LeetCode hot100 回溯专题总结:Java 通用模板、决策树模型
java·算法·leetcode·决策树
2601_962218619 小时前
万象生鲜系统订单全生命周期状态同步技术实现业务可视
大数据·数据库·人工智能·python·算法
那年窗外下的雪.10 小时前
AIDC 学习日志|第 22 天|All-Active/Single-Active 故障演练设计
服务器·网络·学习·算法·哈希算法
wzdark11 小时前
基于启发式搜索的最优路径规划算法研究4
算法