首页 > 其他分享 >简单dp 学习笔记

简单dp 学习笔记

时间:2024-03-01 14:22:42浏览次数:33  
标签:结点 背包 max 笔记 学习 物品 转移 dp

1. 背包

1.1 背包模型的概述

有 \(n\) 种物品,每种物品有若干个。拿一件物品付出 \(w_i\) 代价获得 \(v_i\) 价值,问最多花费 \(V\) 的代价能获得的最大价值。

1.2 0/1背包

考虑每种物品只有一个的情况。

我们设 \(f_{i,j}\) 表示前 \(i\) 个物品,花费了 \(j\) 的最大价值。

于是得出 dp 方程:\(f_{i,j}=\max(f_{i-1,j},f_{i-1.j-w_i}+v_i)\)。

我们发现,\(f_{i,j}\) 都是从 \(f_{i-1,j}\) 转移而来,所以考虑压掉 \(i\)。需要发现,在转移时要倒序转移,使得每个物体只被选一次。

    for(int i=1; i<=n; i++)
        for(int j=V; j>=w[i]; j--)
            f[j]=max(f[j],f[j-w[i]]+v[i]);

1.3 完全背包问题

即每种物品有无数个。

考虑同样的 dp 转移,只是将倒序枚举改为正序,这样就变成选无限个了。

    for(int i=1; i<=n; i++)
        for(int j=w[i]; j>=V; j++)
            f[j]=max(f[j],f[j-w[i]]+v[i]);

1.4 多重背包问题

给出每种物品有 \(s_i\) 个,怎么做?

一个最简单的想法是直接把 \(s_i\) 个看成不同的 \(s_i\) 种,但是这样的复杂度是 \(O(\sum s\times V)\) 的,不可接受。

考虑倍增,将物品拆成 \(2^0,2^1,2^2,\dots,2^{\log s}\) 个,复杂度变成了 \(O(\sum{\log s}\times V)\) 。

    int cnt=0;
    for(int i=1,v,w,s;i<=n;i++){
        rd(w,v,s);
        for(int j=1; j<=s; j<<=1) w[++cnt]=j*w,v[cnt]=j*v,s-=j;
        if(s) w[++cnt]=s*w,v[cnt]=s*v;
    }
    for(int i=1; i<=cnt; i++)
        for(int j=V; j>=w[i]; j--)
            f[j]=max(f[j],f[j-w[i]]+v[i]);

1.5 “恰好为 V”

问能否从中选取若干件总价值恰好为 \(V\)。

\(f_{i,j}\) 表示前 \(i\) 件物品能否取到恰好 \(j\)。

转移同理。

1.6 有依赖的背包

P1064

考虑依赖关系,对子集进行讨论,枚举子树哪些被选。

1.7 背包的方案计数

考虑如果不需要最优解,直接将取 max 改为求和即可。

否则记 \(g_i\) 表示 \(f_i\) 最大时的方案数,看从哪里转移过来输出即可。

2. 区间 dp

区间 dp 经典方程式:\(f_{i,j}=\max(f_{i,k}+f_{k+1,j}+cost(i,j))\)。

P1880

断环为链,直接做。

3. 树形 dp

3.1 simple

P1352

设 \(f_{i,0/1}\) 表示选/不选 \(i\) 的最优情况。

于是可以知道 \(f_{i,0}=\max(f_{j,0},f_{j,1})+a_i,f_{i,1}=f_{j,0}+a_i\),其中 \(j\) 是 \(i\) 的儿子。

dfs 转移。

3.2 树上背包

P2014

建图,发现是一个森林。

我们设 \(f_{u,i,j}\) 表示以 \(u\) 号点为根的子树中,已经遍历了 \(u\) 号点的前 \(i\) 棵子树,选了 \(j\) 门课程的最大学分。

转移的过程结合了树形 DP 和 背包 的特点,我们枚举 \(u\) 点的每个子结点 \(v\),同时枚举以 \(v\) 为根的子树选了几门课程,将子树的结果合并到 \(u\) 上。

记点 \(x\) 的儿子个数为 \(s_x\),以 \(x\) 为根的子树大小为 \(\textit{siz_x}\),可以写出下面的状态转移方程:

\( f_{u,i,j}=\max_{v,k \leq j,k \leq \textit{siz_v}} f_{u,i-1,j-k}+f_{v,s_v,k} \)

注意上面状态转移方程中的几个限制条件,这些限制条件确保了一些无意义的状态不会被访问到。

\(f\) 的第二维可以很轻松地用滚动数组的方式省略掉,注意这时需要倒序枚举 \(j\) 的值。

可以证明,该做法的时间复杂度为 \(O(nm)\)。

3.3 换根 dp

换根 dp 通过预处理换根的贡献,使得仅用两次 dfs 可以处理一些问题。

通常在出现在无根树或者需要对每个点计算答案时考虑换根。

P3478"

不妨令 \(u\) 为当前结点,\(v\) 为当前结点的子结点。首先需要用 \(s_i\) 来表示以 \(i\) 为根的子树中的结点个数。\(s_u=1+\sum s_v\)。
考虑计 \(f_u\) 为以 \(u\) 为根时,所有结点的深度之和。

考虑让根从 u 换到 v,这样 v 的子树中的点的 dep--, v 字数外的点的 dep++,可以知道 \(f_v=f_u+n-2\times s_v\)。

直接转移即可。

4.DAG 上 dp

考虑拓扑排序,从入度为 0 的点开始记忆化搜索,这样可以方便的计算答案。

标签:结点,背包,max,笔记,学习,物品,转移,dp
From: https://www.cnblogs.com/lgh-blog/p/18046725

相关文章

  • 读书笔记2
    1.1节通过三个简短的对话,启发我对什么是程序,什么是软件,什么是软件工程,也了解到了一个软件不是简简单单就能说写就写的,还需要考虑各种因素,如人们的需求,功能的可行性。1.2节详细的给软件工程下定义,介绍软件工程的特殊性,介绍软件工程中的“工程”的由来,讲述了软件工程与计算机科学的......
  • faster-fifo:C++实现的python多进程通信队列 —— 强化学习ppo算法库sample-factory的C
    项目地址:https://github.com/alex-petrenko/faster-fifo需要注意,该项目给出了两种安装方法,一种是pip从pypi官网安装,一种是从GitHub上的源码安装;经过测试发现这个项目维护程度较差,因此pypi官网上的项目比较落后,因此不建议使用pypi上的安装,而是进行源码编译安装。给出源码编......
  • 程序是怎样跑起来的第三章读书笔记
    第三章主要讲了计算机进行小数运算时出错的原因包括3.1将0.1累加一百次也得不到十(首先书本中列举了一个计算机运算错误的例子,代码清单3-1的程序运行后显示器上显示的结果并不是10,程序没错计算器也没发生故障用这个角度展开了计算机是如何处理小数的)3.2用二进制表示小数(对整......
  • 读书笔记
    《程序员修炼之道》是由AndrewHunt和DavidThomas合著的一本经典编程书籍。这本书不仅仅关注编码技术,还强调软件开发中的实践、原则和技巧。以下是一些读者通常提到的主要观点:1.实用性强:书中提供了很多实用的建议,帮助程序员提高编程技能和职业素养。2.注重实践:作者强调实际编......
  • 读书笔记(1)
    第一章概论:1.“软件=程序+软件工程”问题:程序与软件的区别是什么?回答:以前我总是分不清何为程序,何为软件,一直以为比较完善的程序就是一个软件。于是,我上网查了资料,更加明确两者的区别:程序(program)是为实现特定目标或解决特定问题而用计算机语言编写的命令序列的集合。为进行某......
  • 读书笔记(2)
    第二章个人技术与流程1.2.1.1用VSTS写单元测试在该部分,举的例子是用c#写的,因为之前并没有了解这部分的内容,所以,看起书来不是很懂。希望老师在上课时能用同学们学过的Java或者c语言举例给同学们讲解一下。2.“最好在设计的时候就写好单元测试,这样单元测试就能体现API的语义如......
  • 基于CNN+LSTM深度学习网络的时间序列预测matlab仿真
    1.算法运行效果图预览  2.算法运行软件版本MATLAB2022a 3.算法理论概述      时间序列预测是指利用历史数据来预测未来数据点或数据序列的任务。在时间序列分析中,数据点的顺序和时间间隔都是重要的信息。CNN+LSTM网络结合了卷积神经网络(CNN)的特征提取能力和长......
  • Go语言精进之路读书笔记第41条——有层次地组织测试代码
    聚焦位于测试包内的测试代码该如何组织41.1经典模式—平铺测试函数各自独立,测试函数之间没有层级关系,所有测试平铺在顶层41.2Unit家族模式测试套件(TestSuite)和测试用例(TestCase)41.3测试固件测试固件是一个人造的、确定性的缓解,在这个环境中进行测试,测试结果是可重复的......
  • MarkDown学习
    MarkDown学习标题34字体ctrl+b粗体;hello,world!ctrl+i斜体;hello,world!ctrl+u下划线hello,world!hello,world!引用选择狂神Java(>)分割线---or***图片超链接点击跳转列表A1.空格BCA-空格BC表格ctrl+t代码pub......
  • Vue学习笔记28--v-cloak
    v-cloak  总结:v-cloak(没有值):<br>   1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。<br>   2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"&g......