dp 总结 1

dp 总结 1

闲来无事, 把刚学明白的 dp 笔记整理一下.

shout out to professor Adzlpxsn.

基本的, 状态, 转移, 方程

状态

一句话概况即为当前的属性.

比如说, 贝贝现在是 \(30\) 岁, 发了 \(0\) 张专辑, 我们就可以说 \(f_{30}=0\).

这里我们说 \(30\)\(0\) 是不同的信息, 所以一个状态 \(f_{x}=y\) 里包含的信息其实有 \(x\)\(y\).

同样的, \(f_{x,y}=z\) 里包含的信息有 \(3\) 个, 即 \(x\) \(y\) \(z\).

转移

转移, 就是说用 \(f_{x}\) 推算 \(f_{y}\), 或者用 \(f_{x}\)\(f_{y}\) 推算 \(f_{z}\).

举个例子.

贝贝的新专辑 "金手指", 第 \(x\) 首歌是 boombap 还是 trap 取决于第 \(x-1\) 首和第 \(x-2\) 首, 即 \(f_{x}=(f_{x-1}+f_{x-2}) \bmod 2\). 那么我们就说 \(f_{x}\)\(f_{x-1}\)\(f_{x-2}\) 转移而来.

方程

方程就是把转移的过程写成人类能看懂的东西, 比如 "数学语言" "自然语言" "编程语言".

线性 dp

最简单的线性 dp, 就是跳跃问题.

problem:AtCoder-dp_a

考虑状态, 我们让 \(f_{x}\) 表示现在位于 \(stone_{x}\) 时最少跳了多少.

转移就比较容易了, \(f_{x}=\operatorname{std::min}(f_{x-2}+|h_{x-2}-h_{x}|,f_{x-1}+|h_{x-1}-h_{x}|)\).

没什么好讲的, 注意边界条件初始化就好了, 难的题就很难.

背包 dp

这个就好玩了.

01 背包

我个人觉得背包 dp 和线性 dp 大抵是有血缘关系的罢.

problem:AtCoder-dp_d

可以想到, 我们让 \(f_{c}\) 表示在背包容量为 \(c\) 时的最大价值.

于是有转移方程 \(f_{c}=\operatorname{std::max}(f_{c},f_{c-w_{x}}+v_{x})\).

那么这时候我们有一个问题.

如果内层循环从 \(w_{x}\) 枚举到 \(W\), 那么有可能会造成重复选择, 但题意说每个物品只有 \(1\) 个.

于是我们可以调转内层循环的方向, 从 \(W\) 枚举到 \(w_{x}\), 此时每个物品就只会被选一次了.

代码

/* by 01022.hk - online tools website : 01022.hk/zh/dnsdx.html */
for(ll	x=1;x<=n;x++)	// 枚举每个物品
	for(ll	c=W;w[x]<=c;c--)	// 枚举背包大小
		f[c]=std::max(f[c],f[c-w[x]]+v[x]);	// 转移
std::cout<<f[W]<<"\n";

完全背包

再考虑, 如果每个物品可以选无数次呢?

problem:洛谷-P1616

显然, 只要把内层循环的方向调回去就可以了.

/* by 01022.hk - online tools website : 01022.hk/zh/dnsdx.html */
for(ll	x=1;x<=n;x++)	// 枚举每个物品
	for(ll	c=w[x];c<=W;c++)	// 枚举背包大小
		f[c]=std::max(f[c],f[c-w[x]]+v[x]);	// 转移
std::cout<<f[W]<<"\n";

多重背包

现在我们说, 每个物品不止有 \(1\) 个, 但也不能无限选, 于是我们说物品 \(x\)\(t_{x}\) 个, 这就是多重背包.

problem:洛谷-1776

如果当成 \(t_{x}\) 个相同物品那么显然会超时, 因为 \(\sum\limits_{x\in[1,n]}t_{x}\ge+\infin\).

于是我们想, 我们学计算机最重要的是什么? 是二进制.

是的, 我们只要拆分成二进制就好了.

std::vector<td>v,w;
for(td	x=1;x<=n;x++){
	td	vx,wx,tx;
	std::cin>>vx>>wx>>tx;
	for(td	f=1;f<=tx;f<<=1){	// 二进制分解
		v.emplace_back(vx*f);
		w.emplace_back(wx*f);
		tx-=f;
	}	if(tx!=0){	// 最后还剩一点点, 单独做成一个
		v.emplace_back(vx*tx);
		w.emplace_back(wx*tx);
	}
}

然后跑一遍 01 背包就解决了.

分组背包

当每一组物品里只能选 \(1\) 个的时候应该怎么办呢?

problem:洛谷-P1757

这里留给读者思考, 简单放一下代码, 和 01 背包也差不多.

ll	t=0;
std::vector<std::vector<ll>>g(n+1);
for(ll	x=1;x<=n;x++){
	ll	s;
	std::cin>>w[x]>>v[x]>>s;
	t=std::max(t,s);
	g[s].emplace_back(x);
}
for(ll	s=1;s<=t;s++)
	for(ll	c=W;0<=c;c--)
		for(ll	x:g[s])
			if(w[x]<=c)
				f[c]=std::max(f[c],f[c-w[x]]+v[x]);
std::cout<<f[W]<<"\n";

时间复杂度总结

像线性 dp 就是 \(O(n*k)\), 其中 \(k\) 为转移复杂度, 比如之后会讲的优化就能搞出 \(k=\log n\).

背包 dp 就比较固定了, 都是 \(O(n*W)\). 特别的, 由于多重背包是二进制搞来的, 所以多重背包的 \(n'=\sum\limits_{x\in[1,n]}\log x\)

下期预告

区间 dp, 状压 dp.

原文来自CnBlogs, 作者: young_tea.
内容概要:本文介绍了一个基于Matlab的综合能源系统优化调度仿真资源,重点实现了含光热电站、有机朗肯循环(ORC)和电含光热电站、有机有机朗肯循环、P2G的综合能源优化调度(Matlab代码实现)转气(P2G)技术的冷、热、电多能互补系统的优化调度模型。该模型充分考虑多种能源形式的协同转换与利用,通过Matlab代码构建系统架构、设定约束条件并求解优化目标,旨在提升综合能源系统的运行效率与经济性,同时兼顾灵活性供需不确定性下的储能优化配置问题。文中还提到了相关仿真技术支持,如YALMIP工具包的应用,适用于复杂能源系统的建模与求解。; 适合人群:具备一定Matlab编程基础和能源系统背景知识的科研人员、研究生及工程技术人员,尤其适合从事综合能源系统、可再生能源利用、电力系统优化等方向的研究者。; 使用场景及目标:①研究含光热、ORC和P2G的多能系统协调调度机制;②开展考虑不确定性的储能优化配置与经济调度仿真;③学习Matlab在能源系统优化中的建模与求解方法,复现高水平论文(如EI期刊)中的算法案例。; 阅读建议:建议读者结合文档提供的网盘资源,下载完整代码和案例文件,按照目录顺序逐步学习,重点关注模型构建逻辑、约束设置与求解器调用方式,并通过修改参数进行仿真实验,加深对综合能源系统优化调度的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值