【状态机dp 动态规划】100290. 使矩阵满足条件的最少操作次数

简介: 【状态机dp 动态规划】100290. 使矩阵满足条件的最少操作次数

本文涉及知识点

动态规划汇总

状态机dp

LeetCode100290. 使矩阵满足条件的最少操作次数

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

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

如果右边相邻格子存在的话,它们的值不相等,也就是 grid[i][j] != grid[i][j + 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 次操作:

将 grid[1][0] 变为 1 。

将 grid[0][1] 变为 0 。

将 grid[1][2] 变为 1 。

示例 3:

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

输出:2

解释:

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

提示:

1 <= n, m <= 1000

0 <= grid[i][j] <= 9

原理

本题    ⟺    \iff 各列相同,相邻列不等。

操作后,一定存在最优解,各列的值全部∈ \in[0,9]。

将某列全部变成x,需要的操作次数 n - cnt[x],如果x<0或x>9,则cnt[x]一定为0。故将x换成y(y∈ \in[0,9]),操作次数只会减少或不变。

如果某个最优解第col列小于0或大于9。则换成[0,9]之内和col-1列,col+1列不同的数。

动态规划

动态规划的状态表示

pre[iPre]表示处理完前c列,以iPre结束的最少操作次数。

dp[cur]表示处理完前c+1列,以cur结束的最少操作次数。

空间复杂度:O(10)

动态规划的转移方程

image.png

动态规划的初始值

pre全为0。

动态规划的填表顺序

从第0列到最后一列。

动态规划的返回值

pre的最小值。

代码

template<class ELE,class ELE2>
void MinSelf(ELE* seft, const ELE2& other)
{
  *seft = min(*seft,(ELE) other);
}
template<class ELE>
void MaxSelf(ELE* seft, const ELE& other)
{
  *seft = max(*seft, other);
}
class Solution {
public:
    int minimumOperations(vector<vector<int>>& grid) {
        m_r = grid.size();
        m_c = grid[0].size();
        vector<int> pre(10);
        for (int c = 0; c < m_c; c++) {
            int cnt[10] = { 0 };
            for (int r = 0; r < m_r; r++) {
                cnt[grid[r][c]]++;
            }
            vector<int> dp(10,2'000'000);
            for (int iPre = 0; iPre < 10; iPre++) {
                for (int cur = 0; cur < 10; cur++) {
                    if (iPre == cur) { continue; }
                    MinSelf(&dp[cur], pre[iPre] + m_r - cnt[cur]);
                }
            }
            pre.swap(dp);
        }
        return *std::min_element(pre.begin(), pre.end());
    }
    int m_r, m_c;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

相关文章
|
弹性计算 Linux Shell
ECS基本命令及简单应用
本场景介绍如何申请阿里云ECS环境资料,并在其下进行基本的Linux命令操作。
|
2月前
|
Ubuntu 关系型数据库 MySQL
MySQL包安装 -- Debian系列(离线DEB包安装MySQL)
本文详细介绍了在Ubuntu 24.04、22.04、20.04及Debian 12系统上,通过离线DEB包安装MySQL 8.0和8.4版本的完整步骤。涵盖下载地址、依赖处理、dpkg安装顺序、配置方法及服务启动验证,确保用户可顺利部署MySQL数据库。
906 0
MySQL包安装 -- Debian系列(离线DEB包安装MySQL)
|
11月前
|
机器学习/深度学习 算法 前端开发
图解前向、反向传播算法,一看就懂!
前向传播是神经网络中信息从输入层经过隐藏层传递到输出层的过程。每个神经元接收前一层的输出,通过加权求和和激活函数处理后传递给下一层,最终生成预测结果。此过程涉及输入信号、加权求和、激活函数应用等步骤。前向传播用于生成预测结果,在训练阶段与真实标签比较以计算损失函数,并在推理阶段直接生成预测值。反向传播则利用链式法则计算损失函数相对于权重的梯度,调整参数以减小误差,从而优化模型性能。两者结合实现神经网络的有效训练和预测。
|
存储 缓存 算法
C语言在实现高效算法方面的特点与优势,包括高效性、灵活性、可移植性和底层访问能力
本文探讨了C语言在实现高效算法方面的特点与优势,包括高效性、灵活性、可移植性和底层访问能力。文章还分析了数据结构的选择与优化、算法设计的优化策略、内存管理和代码优化技巧,并通过实际案例展示了C语言在排序和图遍历算法中的高效实现。
383 2
|
人工智能 算法 C语言
详解树状数组(C/C++)
详解树状数组(C/C++)
|
机器学习/深度学习 算法 数据挖掘
8个常见的机器学习算法的计算复杂度总结
8个常见的机器学习算法的计算复杂度总结
325 4
8个常见的机器学习算法的计算复杂度总结
|
存储 算法 C++
高精度算法(加、减、乘、除,使用c++实现)
高精度算法(加、减、乘、除,使用c++实现)
2958 0
高精度算法(加、减、乘、除,使用c++实现)
|
自然语言处理 安全 Java
java中如何实现多语言切换
java中如何实现多语言切换
814 2
|
机器学习/深度学习 传感器 算法
强化学习(RL)在机器人领域的应用,尤其是结合ROS(Robot Operating System)和Gazebo(机器人仿真环境)
强化学习(RL)在机器人领域的应用,尤其是结合ROS(Robot Operating System)和Gazebo(机器人仿真环境)
797 2
|
JavaScript 前端开发
前端 JS 经典:宏任务、微任务、事件循环(EventLoop)
前端 JS 经典:宏任务、微任务、事件循环(EventLoop)
228 0

热门文章

最新文章