力扣--1411. 给 N x 3 网格图涂色的方案数

力扣--1411. 给 N x 3 网格图涂色的方案数

目录

前言:

题目:

题目分析:

代码一:

代码二:

代码一分析:

代码二分析(公式推导):

关键观察:每行只有两种模式

类型 1:ABA 型(首尾相同)

类型 2:ABC 型(三色全不同)

动态规划状态设计

推导转移关系(关键!)

结语:


前言:

这是力扣的一个题目,很经典!就是找不到规律和找到规律,写代码完全不是一个级别!希望这篇可以给大家参考,我刚开始做的时候也想找规律,但是没找到,没有理解到意思!

题目:

你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同)。

给你网格图的行数 n 。

请你返回给 grid 涂色的方案数。由于答案可能会非常大,请你返回答案对 10^9 + 7 取余的结果。

示例 1:

  • 输入:n = 1
  • 输出:12

解释:总共有 12 种可行的方法:

示例 2:

  • 输入:n = 2
  • 输出:54

示例 3:

  • 输入:n = 3
  • 输出:246

示例 4:

  • 输入:n = 7
  • 输出:106494

示例 5:

  • 输入:n = 5000
  • 输出:30228214

提示:

  • n == grid.length
  • grid[i].length == 3
  • 1 <= n <= 5000

题目分析:

第一个代码,先考虑暴力搜索,枚举每个格子涂哪种颜色。

第二个代码,可以找到规律:

这个涂色问题的答案满足一个递推公式

f(n) = 5 × f(n-1) - 2 × f(n-2)

其中:

  • f(1) = 12
  • f(2) = 54
  • f(3) = 5×54 - 2×12 = 270 - 24 = 246
  • f(4) = 5×246 - 2×54 = 1122
  • ……

为了能让这个公式从 n=2 开始算,我们人为定义一个 f(0) = 3(它没有实际意义,只是为了公式成立)。

验证一下:

  • f(2) = 5×f(1) - 2×f(0) = 5×12 - 2×3 = 60 - 6 = 54 ✅

代码一:

代码二:

代码一分析:

代码一采用DFS+记忆化的方法,从下往上逐格涂色:

  1. 状态表示
    • (i, j) 表示当前正在涂第 i 行第 j 列
    • preRow 表示下一行(i+1行)的颜色状态(用6位二进制表示)
    • curRow 表示当前行已涂色的状态
  2. 状态转移
    • 每个格子尝试三种颜色
    • 需要检查:不能与下方格子颜色相同,不能与左侧格子颜色相同
    • 使用位运算高效地存储和检查颜色状态
  3. 记忆化优化
    • 将(i, j, preRow, curRow)压缩为一个整数作为key
    • 避免重复计算相同状态

代码二分析(公式推导):

关键观察:每行只有两种模式

由于每行只有 3 个格子,且左右不能同色,我们可以枚举所有合法的单行涂色方式。

用三种颜色 A、B、C 表示,合法的行模式只有两类:

类型 1:ABA 型(首尾相同)

例如:红-黄-红、蓝-红-蓝
→ 满足:color[0] == color[2] != color[1]

类型 2:ABC 型(三色全不同)

例如:红-黄-蓝、蓝-绿-红
→ 满足:color[0] != color[1] != color[2]color[0] != color[2]

💡 总共合法单行方案数:ABA 型:3 × 2 = 6 种(选首尾颜色 3 种,中间不同 2 种)ABC 型:3 × 2 × 1 = 6 种共 12 种 → 所以 f(1) = 12

动态规划状态设计

设:

  • a[i] = 第 i 行是 ABA 型 的方案总数
  • b[i] = 第 i 行是 ABC 型 的方案总数

则总方案数:f[i] = a[i] + b[i]

推导转移关系(关键!)

考虑第 i-1 行和第 i 行的颜色不能上下相同:

上一行类型下一行可接的 ABA 数量下一行可接的 ABC 数量
ABA32
ABC22

这个可以通过枚举验证(略,但标准结论如此)

于是得到递推式:

所以总方案数:

但我们希望只用 f[i] 表示。注意到:

  • f[i-1] = a[i-1] + b[i-1]
  • f[i-2] = a[i-2] + b[i-2]

通过代数消元(或矩阵快速幂特征方程),可以推出一个二阶线性递推式

f[i] = 5 * f[i-1] - 2 * f[i-2]

结语:

网格涂色问题展示了两种不同的解题思路:

  1. 通用方法(记忆化搜索):适合大多数约束满足问题,通过状态压缩和记忆化优化,可以处理中等规模的问题。
  2. 特殊方法(数学推导):通过发现问题的内在规律,得到简洁的递推公式,适用于大规模输入。

对于本题,由于n最大可达5000,数学递推方法明显更优。这也提醒我们,在解决算法问题时,不仅要掌握通用的解题技巧,也要注意观察问题特点,寻找更高效的专用解法。

推荐使用代码二的递推方法,它不仅效率高,而且代码简洁,是解决此类问题的优选方案。

希望这对大家有所帮助!一起加油!

Read more

安利一款超实用的前端可视化打印设计器:Vue Print Designer

安利一款超实用的前端可视化打印设计器:Vue Print Designer

做前端开发的朋友应该都懂,业务开发中遇到打印需求真的头大 —— 手写分页逻辑繁琐、不同框架适配麻烦、票据 / 快递单这类定制化打印场景不好实现,找个趁手的打印插件更是难上加难。最近发现了一款开源的可视化打印设计器Vue Print Designer,完美解决了这些痛点,不管是快速开发还是企业级定制化需求都能满足,今天就跟大家详细聊聊这款工具。 一、Vue Print Designer 是什么? Vue Print Designer 是一款面向业务表单、标签、票据、快递单等打印场景的可视化设计器,核心主打模板化、变量化设计,还提供了静默打印、云打印能力,同时支持 PDF / 图片 / Blob 等多种导出方式,完全能覆盖日常开发中的各类打印需求。 它不是简单的打印插件,而是一套完整的打印解决方案,从可视化设计模板,到参数配置、多端打印,再到定制化扩展,一站式搞定,而且项目还在持续更新,最新版本已经支持英寸、厘米作为单位,对国际化和精细化设计更友好了。 项目地址:https://gitee.com/

By Ne0inhk
我的算法修炼之路--5——专破“思维陷阱”,那些让你拍案叫绝的非常规秒解

我的算法修炼之路--5——专破“思维陷阱”,那些让你拍案叫绝的非常规秒解

💗博主介绍:计算机专业的一枚大学生 来自重庆 @燃于AC之乐✌专注于C++技术栈,算法,竞赛领域,技术学习和项目实战✌💗 💗根据博主的学习进度更新(可能不及时) 💗后续更新主要内容:C语言,数据结构,C++、linux(系统编程和网络编程)、MySQL、Redis、QT、Python、Git、爬虫、数据可视化、小程序、AI大模型接入,C++实战项目与学习分享。 👇🏻 精彩专栏 推荐订阅👇🏻 点击进入🌌作者专栏🌌: 算法画解 ✅ C++ ✅ 🌟算法相关题目点击即可进入实操🌟 感兴趣的可以先收藏起来,请多多支持,还有大家有相关问题都可以给我留言咨询,希望希望共同交流心得,一起进步,你我陪伴,学习路上不孤单! 文章目录 * 前言 * 题目清单 * 1.Metoer Shower(流星雨) * 2.

By Ne0inhk

Flutter 三方库 serial 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、稳定的 Web 串口通信与工业硬软连接实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 serial 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、稳定的 Web 串口通信与工业硬软连接实战 在鸿蒙(OpenHarmony)系统的工业平板、手持 PDA 及桌面协同场景中,如何通过 Web 容器直接操控外部硬件设备(如扫码枪、打印机、传感器)?serial 做为一个优秀的 window.navigator.serial API 的 Flutter 封装库,为鸿蒙开发者提供了跨平台的硬件底座。本文将深入探讨其在鸿蒙生态中的适配要点。 前言 什么是 Web Serial?它允许鸿蒙应用内的 Web 组件直接请求访问用户的串行设备。在 Flutter for OpenHarmony 的实际开发中,serial

By Ne0inhk
【算法】【优选算法】哈希表

【算法】【优选算法】哈希表

目录 * 一、简介 * 二、两数之和 * 三、⾯试题 01.02.判定是否互为字符重排 * 四、217.存在重复元素 * 五、219.存在重复元素 II * 六、49.字⺟异位词分组 一、简介 哈希表就是一个使用键值对key-value来存储数据的容器。 用于快速查找某个元素O(1)时间复杂度。 * 应用场景: 频繁查找元素的时候。 * 使用方法 * 语言自带的集合类 * 使用数组模拟,用下标来当key值。 二、两数之和 题目链接:1.两数之和 题目描述: 解题思路: * 使用一个hash容器,将数组以数组元素-下标的形式存储起来, * 再遍历数组,当hash表中有与当前数组元素加起来等于target的并且不是同一个元素的返回即可。 解题代码: //时间复杂度:O(n)//空间复杂度:O(

By Ne0inhk