【动态规划】似包非包

【动态规划】似包非包

似包非包

1.组合总和 Ⅳ

题目链接:377. 组合总和 Ⅳ

题目分析:

在这里插入图片描述

看完题目要求,在看示例1,你可能会想到这是一个完全背包问题。但是如果这道题真的问的是组合的话,前面出现 (1,1,2) 后面就不会出现(1,2,1) 和 (2,1,1)这样的情况。题目把这三种情况当成了不同的情况。也就是顺序不一样它们也是属于不同组合。

但是实际上 排列组合 是不一样的,排列是有序的,组合是无序的。

如果这道题问题的是组合,也就不考虑选出来数的顺序,那(1,1,2) 、(1,2,1) 、 (2,1,1)就只属于一种情况,不管它是什么组合。

而排序是有序的,要保证选出来数的先后顺序。

所以这道题应该叫做排列总和才对。

算法原理:

实质上背包问题都是解决这一类问题:有限制条件下的 “组合” 问题

从状态表示

dp[i][j] 表示:从前 i 个物品中挑选,总体积不超过 j,所有的选法中,最大的价值

来看,我们的状态表示从来没有规定过挑选的顺序。而只是在两个限定条件下,所有的选法中,要最大价值即可。

因此我们挑选出来的所有选法都是没有顺序的。所以背包问题实质上解决的 “组合” 问题。

当用背包问题去解决方案数的时候,其实求的是 ''组合" 数。而这道题问的是组合数实际上求的是排序数。所以这道题不能用背包问题解决。

我们就用常规的状态表示来分析这道题。

1.状态表示

这里我们学一种新的状态表示法。之前做的大多数问题都是用的是线性dp或者区间dp来解决,所以之前的经验都是以某个位置为结尾,巴拉巴拉。或者以某个位置为起点,巴拉巴拉。或者选取一段区间巴拉巴拉。

但是这道题既不像线性dp也不像区间dp,我们可以这样来:

根据分析问题的过程中,发现重复子问题,抽象出来一个状态表示。

接下来以一个例子来说什么是重复子问题。比如这道题,给我们一堆数假设是[a、b、c、d],然后看看凑成target,一共有多少种排列数。如果要看排列数一定要看看每个位置怎么选,因为每个位置选数要考虑先后顺序。假设凑成target需要四个位置,第一个位置可以选[a、b、c、d]、第二个位置也可以选[a、b、c、d]…,如果第一个位置放了a,那接下来就看剩下的位置凑出来target - a。重复的问题是本来想要的是整个区间凑成target,然后固定一个数之后发现整个区间凑成target - a 就可以了。也就是说我们的相同问题是看凑成一个数有多少种方法。本来想看凑成target有多少种方法,接下来就是去看target - a 有多少种方法。这就是重复子问题。

在这里插入图片描述

接下来将重复子问题,抽象出来一个状态表示。想看一个数有多少种话,我们搞一个一维数组。

dp[i] 表示:凑成总和为 i,一共有多少种排列数。

在这里插入图片描述

本来想看凑成target有多少种方法,接下来发现固定完一个数就是去看target - a 有多少种方法。这就是根据分析问题的过程中,发现重复子问题,抽象出来一个状态表示

2.状态转移方程

如果能用上面那种方式定义状态表示,其实状态转移方程就和上面一模一样。
我们用一条线长度表示target。我们细贯用最后一个位置划分情况。

假设最后一个位置的数是nums[j](0 <= j <= n.size()) 表示数组里任意一个数都可以放到最后一个位置。

如果最后一个位置放的是nums[j],整体想凑成总和 i ,那仅需看看前

Read more

ZEEKLOG博客推荐:2025年最值得尝试的开源ASR工具

2025年最值得尝试的开源ASR工具:Fun-ASR深度解析 在智能办公、远程协作和语音交互日益普及的今天,如何高效地将会议录音、客户通话或访谈内容转化为可编辑的文字,已成为企业和开发者面临的核心挑战之一。尽管市面上已有不少商业语音识别API,但高昂的成本、数据外传的风险以及对专业术语识别不准等问题,始终制约着其在敏感场景中的广泛应用。 正是在这样的背景下,由钉钉与通义实验室联合推出、开发者“科哥”主导构建的 Fun-ASR 横空出世。这款基于大模型的开源语音识别系统,不仅实现了接近实时的转写速度和高精度中文识别能力,更通过一个简洁直观的WebUI界面,让非技术人员也能轻松完成批量语音处理任务。它不是简单的技术堆砌,而是一次面向真实使用场景的工程重构——将高性能、易用性与隐私保护真正融合在一起。 从端到端架构看Fun-ASR的技术实现 Fun-ASR 的核心是名为 Fun-ASR-Nano-2512 的端到端语音识别模型,采用Transformer-based结构设计,能够直接将音频信号映射为文本输出,跳过了传统ASR中复杂的声学模型、语言模型分离训练流程。整个识别过程被拆解

By Ne0inhk

GitHub 2FA双重验证实战指南:从Edge插件到扫码一步到位

1. 为什么你的GitHub账户急需2FA?一个真实的故事 前几天,一个朋友半夜给我发消息,语气都快哭了。他辛辛苦苦维护了两年的开源项目,代码仓库突然被清空了,还被人用他的账号发了一堆垃圾信息。他第一反应是密码泄露了,但密码是他用密码管理器生成的、又长又复杂的唯一密码。问题出在哪?后来GitHub支持团队回复说,他的账户遭遇了“凭证填充”攻击。简单说,就是黑客用从其他网站泄露的账号密码,来批量“撞”GitHub的登录。只要密码不幸在其他地方重复使用了,哪怕再复杂,也形同虚设。 这件事让我后背发凉,也让我下定决心,必须把双重验证(2FA)这个“防盗门”给身边每一个开发者朋友都安上。你可能觉得,我的代码又不值钱,谁会来黑我?这个想法太危险了。你的GitHub账户远不止是一个代码托管平台。它关联着你的数字身份,是你技术能力的名片,可能链接着你的云服务密钥、CI/CD流水线,甚至是公司的私有仓库。一旦失守,损失的可能不只是代码,更是信誉和机会。 GitHub官方也一直在大力推动2FA。现在,很多敏感操作,比如修改密码、

By Ne0inhk
Linux系统学习【深入剖析Git的原理和使用(上)】

Linux系统学习【深入剖析Git的原理和使用(上)】

🔥承渊政道:个人主页 ❄️个人专栏: 《C语言基础语法知识》《数据结构与算法》 《C++知识内容》《Linux系统知识》 ✨逆境不吐心中苦,顺境不忘来时路!🎬 博主简介: 引言:在软件开发的全流程中,版本控制是保障协作效率、规避开发风险的核心基石,而Git作为目前最流行、最强大的分布式版本控制系统,早已渗透到从个人开发到大型企业级项目的每一个环节.无论是多人协作时的代码冲突解决、开发过程中的版本回溯,还是跨环境的代码同步、分支管理,Git都以其高效、安全、灵活的特性,成为开发者必备的核心工具.然而,多数开发者对Git的使用仍停留在“会用基础命令”的层面——知道用git add提交暂存、git commit提交本地、git push推送远程,却未必理解这些命令背后的底层逻辑:暂存区(Stage)、本地仓库(Local Repository)、远程仓库(Remote Repository)之间的数据流是怎样的?Git如何高效追踪文件的每一次变更?分布式架构与SVN等集中式版本控制系统相比,核心优势到底体现在哪里? 基于此,

By Ne0inhk
超详细!零基础教你如何将项目代码推送到私人或公共github仓库!!

超详细!零基础教你如何将项目代码推送到私人或公共github仓库!!

前言:本文专为零基础开发者、刚接触GitHub的新手编写,全程图文式步骤(关键命令标红),Windows/macOS/Linux系统通用,无需复杂配置,跟着操作就能快速将本地代码上传到GitHub私人账号,避免踩坑! 一、前期准备工作(3步搞定,缺一不可) 1. 拥有GitHub私人账号并登录 如果还没有GitHub账号,先完成注册: ✅ 访问 GitHub官网,填写用户名、邮箱、密码,完成邮箱验证后即可注册成功; ✅ 注册完成后,登录你的私人账号(后续所有操作均基于已登录状态)。 2. 本地安装Git并配置用户信息(核心步骤) Git是连接本地代码和GitHub远程仓库的核心工具,必须先安装,再配置与GitHub账号一致的信息,否则无法推送代码。 (1)Git安装(分系统操作,默认下一步即可) * Windows系统:访问 Git官网下载安装包,安装时务必勾选「Add Git to PATH」(方便后续在命令行调用Git),其余默认下一步; * macOS系统:

By Ne0inhk