Peter算法小课堂—动态规划

news/发布时间2024/9/20 5:37:18

Peter来啦,好久没有更新了呢

今天,我们来讨论讨论提高组的动态规划。

动态规划

动态规划有好多经典的题,有什么背包问题、正整数拆分、杨辉三角……但是,如果考到陌生的题,怎么办呢?比如说2000年提高组的乘积最大、石子合并……,所以说,我们要理解动态规划的本质。

那么,我们动态规划的第一步就是状态定义

dp的第二步就是填表格、写状态转移方程。

最后一步就是根据状态转移方程写代码了。其实,我觉得,dp最难的地方就是第二步,其次就是根据递推式写代码。给大家练一练根据递推式写代码吧。

递推1

那么,代码很简单,长这样👇

#include<bits/stdc++.h>
using namespace std;
int f[110][1010],n,v,c[110],w[110];
int main()
{scanf("%d%d",&v,&n);for (int i=1;i<=n;++i)scanf("%d%d",&c[i],&w[i]);for (int i=1;i<=n;++i) {for (int j=1;j<c[i];++j)f[i][j]=f[i-1][j];for (int j=c[i];j<=v;++j)f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]);}printf("%d\n",f[n][v]);return 0;
}

再来一道题

递推2

代码长这样

#include<bits/stdc++.h>
using namespace std;
int f[1010],n,c[1010];
int main()
{scanf("%d",&n);for (int i=1;i<=n;++i)scanf("%d",&c[i]);for (int i=1;i<=n;++i)for (int j=1;j<=i;++j)f[i]=max(f[i],f[i-j]+c[j]);int k,x;scanf("%d",&k);for (int i=1;i<=k;++i) {scanf("%d",&x);printf("%d\n",f[x]);}return 0;
}

递推练完了,就要练习状态转移方程了(靠自觉)

摆花

原题链接:P1077 [NOIP2012 普及组] 摆花 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

那么这道题,我们把题意抽象化成:有 n 个数(c1​,c2​,...,cn​),0⩽ci​⩽ai​,求有多少种方案数使\sum_{i=1}^{n}c_{i}=m

首先,看到这道题,我给出5种办法,分别对应初学者、普及Oler、不大聪明的提高Oler、灰常聪明的提高Oler。

初学者

最最最简单的办法就是搜索+记忆化

#include<bits/stdc++.h>
using namespace std;
const int maxn=105, mod = 1000007;
int n, m, a[maxn], rmb[maxn][maxn];
int dfs(int x,int k)
{if(k > m) return 0;if(k == m) return 1;if(x == n+1) return 0;if(rmb[x][k]) return rmb[x][k]; //搜过了就返回int ans = 0;for(int i=0; i<=a[x]; i++) ans = (ans + dfs(x+1, k+i))%mod;rmb[x][k] = ans; //记录当前状态的结果return ans;
}
int main()
{cin>>n>>m;for(int i=1; i<=n; i++) cin>>a[i];cout<<dfs(1,0)<<endl;return 0;
}

搜索所有可能的c_{i}并且记忆化。

普及Oler

其次,应该会想到动态规划了。

时间复杂度大大降低,给出代码

#include <bits/stdc++.h>
using namespace std;
const int N=109;
const int MOD=1e6+7;
int f[N][N],a[N],n,m;
int main(){cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];f[0][0]=1;for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){if(j-1<a[i])f[i][j]=(f[i-1][j]%MOD+f[i][j-1]%MOD)%MOD;else f[i][j]=(f[i-1][j]%MOD+f[i][j-1]%MOD-f[i-1][j-1-a[i]]%MOD+MOD)%MOD;}}cout<<f[n][m]<<endl;return 0;
}

还是比较蒟蒻的

不大聪明的提高Oler

再其次,就是前缀和优化,大家都学过,给出代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 105, mod = 1000007;
int n, m, f[maxn], sum[maxn], a[maxn];
int main(){cin>>n>>m;for(int i=1; i<=n; i++) cin>>a[i];f[0] = 1;for(int i=0; i<=m; i++) sum[i] = 1;for(int i=1; i<=n; i++){for(int j=m; j>=1; j--){int t = j - min(a[i], j) - 1;if(t < 0) f[j] = (f[j] + sum[j-1])%mod;else f[j] = (f[j] + sum[j-1] - sum[t] + mod)%mod;}for(int j=1; j<=m; j++) sum[j] = (sum[j-1] + f[j])%mod;}cout<<f[m]<<endl;return 0;
}

来了,它又来了,它就是我们的生成函数!!!

灰常聪明的提高Oler

生成函数啊啊啊

大家如果不会生成函数的话,可以康康这位大佬的博客生成函数(母函数)——目前最全的讲解-CSDN博客

我们构造一个函数g(x)=\prod_{i=1}^{n}\sum_{j=0}^{a_{i}}x^{j},其中x^{m}项的系数即为答案。可以做n-1次NTT,然后输出。时间复杂度:O(n^2k\log nk)。这里我不给出代码了。

其实,也不用算出乘积,有一种更好的方法

我们约定A(x)=\sum_{i=0}^{n}a_{i}x^{i}B(x)=\sum_{i=0}^{n}b_{i}x^{i}

C(x)=A(x)B(x), 则C(x)=\sum_{i=0}^{n+m}c_{i}x^{i},其中c_{i}=\sum_{j=0}^{i}a_{j}b_{i-j},懂得都懂

这一题比较难,来一道简单亿点的题

参差不齐

n名电影演员依次排成一排,第i人的颜值为y[i],有些参差不齐。你希望挑选m个人拍一张电影海报,这m个人的前后顺序不能发生变化。你希望挑选的这排演员相邻的颜值不能相差太大,于是你定义颜值的参差不齐程度为相邻两人颜值差距的绝对值之和。求这m人的参差不齐程度最少是多少?

这一题最难的是状态定义,要是状态定义完成了的话,状态转移方程就显而易见了。

这个定义不太好,下面给出正确的定义及代码

下面给出代码👇

for(int i=1;i<=n;i++) f[i][1]=0;
for(int j=2;j<=m;j++)//枚举j代表选中人数for(int i=j;i<=n;i++){//枚举i代表结尾编号f[i][j]=INF;for(int k=j-1;k<i;k++)//结尾是i号时枚举k代表i号的左边邻居是几号f[i][j]=min(f[i][j],f[k][j-1]+abs(y[i]-y[k]));}
int ans=INF;
for(int i=m;i<=n;i++) ans=min(ans,f[i][m]);
cout<<ans<<endl;

乘积最大

原题链接:P1018 [NOIP2000 提高组] 乘积最大 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这题显然是一道数位dp

状态定义:f[i][j] 表示前 i 位数包含 j 个乘号所能达到的最大乘积

easy代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long f[45][60];
string in;
int n,k;//n位数  k个乘号 
long long g[45];
long long cut(int l,int r){long long end = 0;for(int i = l;i <= r;i++)end = end * 10 + g[i];return end;
}
int main(){cin >> n >> k >> in;for(int i = 1;i <= n;i++)g[i] = in[i - 1] - '0';for(int i=1;i<=n;i++)f[i][0] = cut(1,i);for(int i = 2;i <= n;i++){ //枚举分割为前i位数字 for(int a = 1;a <= min(i-1,k);a++){ //枚举有几个乘号 for(int b = a;b < i;b++){ //在第几位放乘号 f[i][a] = max(f[i][a],f[b][a-1] * cut(b + 1,i));}}}cout<<f[n][k];return 0;
}

然后,就是我们的毒瘤最后一题啦

面条切割

这一题涉及到动态规划的本质,但是这一题要用到微积分,所以……

原题链接:Problem - 5984 (hdu.edu.cn)

设长度为x的面条期望为f(x)。显然,当x<d时,f(x)=0。当x>b时,设t为0~x上的坐标值,吃掉t~x上的面条,剩下的面条就是0~t,即吃掉剩下的面条次数期望为f(t) 。dt为一个很小的线元,点落在dt上的概率为\frac{dt}{x},而dt贡献的期望为:dt的长度为t,如上所述,贡献了f(t)的期望。最后我们再把这些相加(积分),得到f(x)=1+\frac{\int_{d}^{x} f(t)dt}{x}。接下来就是解出f(x)了。我们可以对f(x)求个导,然后还原,如下(LateX难打)

于是乎,f(x)=\ln x+C。然后,我们代一个特指进去,随便哪一个都行,最好是x=d,然后得到C=1-\ln d。综上所述,f(x)=\ln \frac{d}{x}+1。代码来啦

#include <bits/stdc++.h>
using namespace std;
int main() {int T;cin >> T;while (T--) {double a, b;cin >> a >> b;if (a <= b)cout << "0.000000" << endl;elsecout << fixed << setprecision(6) << 1.0 + log(a / b) << endl;}return 0;
}

时间复杂度几乎为O(1)!

OK!今天就讲到这里,886

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.bcls.cn/iQon/9926.shtml

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

Nacos配置

目录 启动nacos 项目步骤 Nacos服务分级存储模型​编辑 服务跨域集群调用问题 NacosRule负载均衡 服务实例的权重设置 环境隔离-namespace Nacos环境隔离 Nacos和Eureak对比 临时实例和非临时实例 Ncaos与Eureka的共同点 Nacos与Eureka的区别 Nacos配置管理 统一配…

我承认,我低估鸿蒙了 !

2019年&#xff0c;鸿蒙刚出来的时候&#xff0c;我心里是有点犯嘀咕的&#xff0c;虽然很支持国产操作系统&#xff0c;但是我知道&#xff0c;开发操作系统也许不难&#xff0c;但是建立一个全新的生态太难了&#xff01; 如果操作系统中缺乏应用程序&#xff0c;就不会有人…

排序——希尔排序

希尔排序 希尔排序步骤 希尔排序的核心还是插入排序&#xff0c;但是把插入排序分成两部分&#xff0c;1.预排序2.插入排序。先对原数组进行预排序&#xff0c;使数组接近有序&#xff08;让更大的数字和更小的数字更快的分配到两边&#xff09;&#xff0c;然后再对已经接近有…

模拟算法题练习(二)(DNA序列修正、无尽的石头)

目录 &#xff08;一、DNA序列修正&#xff09; 问题分析 方法实现 时间复杂度和空间复杂度分析 &#xff08;二、无尽的石头&#xff09; &#xff08;一、DNA序列修正&#xff09; 问题描述 在生物学中&#xff0c;DNA序列的相似性常被用来研究物种间的亲缘关系。现在我…

MySQL深入——22

kill不掉的语句 在MySQL当中有两个kill命令一个是kill query 线程id表示中止这个线程当中正在执行的语句&#xff0c;另外一个是 kill Connection线程id表示断开这个连接。 在使用MySQL时&#xff0c;使用kill命令之后看show processlist显示的command列为killed&#xff0c;…

《最新出炉》系列初窥篇-Python+Playwright自动化测试-34-处理https 安全问题或者非信任站点-下篇

1.简介 这一篇宏哥主要介绍playwright如何在IE、Chrome和Firefox三个浏览器上处理不信任证书的情况&#xff0c;我们知道&#xff0c;有些网站打开是弹窗&#xff0c;SSL证书不可信任&#xff0c;但是你可以点击高级选项&#xff0c;继续打开不安全的链接。举例来说&#xff0c…

自动化测试摸索:python+selenium+pytest(持续更新.....)

一、环境搭建 1、python 安装 下载链接&#xff1a;Python Releases for Windows | Python.org 自己选择合适的版本下载 当下载完毕时&#xff0c;找到该安装程序&#xff1a;python-3.12.2-amd64.exe文件&#xff0c;双击启动安装向导。 为了防止C:盘文件因系统故障或者无…

CDN原理探究

来源于百度&#xff1a; https://baike.baidu.com/item/%E5%86%85%E5%AE%B9%E5%88%86%E5%8F%91%E7%BD%91%E7%BB%9C/4034265?frge_ala 通过上图&#xff0c;我们可以了解到&#xff0c;使用了CDN缓存后的网站的访问过程变为&#xff1a; 用户向浏览器提供要访问的域名&#xff…

unsigned详讲(干货满满)

前言&#xff1a;过年偷懒了(●ˇ∀ˇ●)&#xff0c;但是年后开学了一定要恢复学习状态&#xff0c;在复习加继续学习的途中&#xff0c;我发现对于unsigned关键字的掌握并不是很熟练&#xff0c;于是翻阅了各个大佬的博客以及书籍&#xff0c;总结了对于unsigned的一些知识点…

pip降级在pycharm中

PyCharm依赖于"–build-dir"参数安装第三方库&#xff0c;但该参数在最新的23.0版pip中已删除 解决办法就是降级pip&#xff0c;PyCharm中选择File&#xff0c;找到编译器&#xff0c;点击pip&#xff0c;勾选对应版本即可 或者在cmd中执行运行python -m pip install…

大语言模型推理加速技术:计算加速篇

原文&#xff1a;大语言模型推理加速技术&#xff1a;计算加速篇 - 知乎 目录 简介 Transformer和Attention 瓶颈 优化目标 计算加速 计算侧优化 KVCache Kernel优化和算子融合 分布式推理 内存IO优化 Flash Attention Flash Decoding Continuous Batching Page…

Redis冲冲冲——事务支持,AOF和RDB持久化

目录 引出Redis事务支持&#xff0c;AOF和RDB持久化1、Redis的事务支持2、Redis的持久化 Redis冲冲冲——缓存三兄弟&#xff1a;缓存击穿、穿透、雪崩缓存击穿缓存穿透缓存雪崩 总结 引出 Redis冲冲冲——事务支持&#xff0c;AOF和RDB持久化 Redis事务支持&#xff0c;AOF和…

Mybatis批量更新对象数据的两种方法

说明&#xff1a;遇到一次需要批量修改对象的场景。传递一个对象集合&#xff0c;需要根据对象ID批量修改数据库数据&#xff0c;使用的是MyBatis框架。查了一些资料&#xff0c;总结出两种实现方式。 创建Demo 首先&#xff0c;创建一个简单的Demo&#xff1b; &#xff08…

K8S存储卷与PV,PVC

一、前言 Kubernetes&#xff08;K8s&#xff09;中的存储卷是用于在容器之间共享数据的一种机制。存储卷可以在多个Pod之间共享数据&#xff0c;并且可以保持数据的持久性&#xff0c;即使Pod被重新调度或者删除&#xff0c;数据也不会丢失。 Kubernetes支持多种类型的存储卷…

C/C++ 迷宫游戏

游戏介绍 这个迷宫探险游戏有以下功能&#xff1a; 探险&#xff1a;选择该选项后&#xff0c;玩家会进入地下迷宫进行探险。在随机事件中&#xff0c;可能会遇到陷阱、发现金币或者什么都没有发生。陷阱会使玩家失去一定的生命值&#xff0c;金币可以增加玩家的金币数量。 休…

C++——内存管理(new和delete)详解

目录 C/C内存管理 案例&#xff1a;变量在内存中到底会在哪&#xff1f; New和delete Operator new和operator delete函数 New和delete的原理 对内置类型 对自定义类型 定位new New/delete和malloc/free的区别 C/C内存管理 C/C内存管理分布图&#xff1a;&#xff08;从…

2024牛客寒假算法基础集训营4

目录 A.柠檬可乐 B.左右互博 C.冬眠 D.守恒 E.漂亮数组 F.来点每日一题 G.数三角形&#xff08;easy&#xff09; A.柠檬可乐 阅读理解题&#xff0c;依照题目直接模拟即可 void solve(){int a,b,k; cin>>a>>b>>k;if(a>k*b) cout<<"go…

【Java】基本数据类型、包装类与字符串间的转换 例题

写在前面&#xff1a; 关于这道题&#xff0c;初见感觉有点cpu烧坏了&#xff0c;准确来说是看了网上的一些讲解都感觉不尽人意。自己整理了一下&#xff0c;希望能帮助到大家。 题目&#xff1a; 如下两个题目输出结果相同吗&#xff1f;各是什么。 Object o1 true ? new…

Java毕业设计-基于springboot开发的Web社区医院管理服务系统-毕业论文+答辩PPT(有源代码)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1.开发说明2.需求分析3、系统功能结构 三、系统实现展示1、系统功能模块2、管理员功能模块3、用户功能模块4、医生功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基于springboot开发…

CGI程序与ShellShock漏洞

CGI是什么&#xff1f; CGI&#xff08;通用网关接口&#xff0c;Common Gateway Interface&#xff09;程序是一种用于在Web服务器上执行动态内容的技术。与服务器上普通的后端代码相比&#xff0c;CGI程序有几个区别&#xff1a; 执行环境&#xff1a; CGI程序在服务器上作为…
推荐文章