Peter算法小课堂—动态规划

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.mzph.cn/news/702185.shtml

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

相关文章

AD24-Gerber生产文件输出及整理

一、Gerber生产文件输出 1、先进行规则检查 2、Gerber Files输出 3、钻孔文件 4、IPC网表 5、坐标文件 二、Gerber Flies文件整理 1、CAM 2、SMT 3、ASM 4、PRJ 5、DXF

ubuntu安装gptsovits

我看到社区有人需要&#xff0c;刚好我自己也要安装个ubuntu的用在自己的4090服务器上玩一玩。 于是就写一篇这样的教程。但是我只需要他的api推理&#xff0c;用于测试4090合成速度。所以这里只执行Python api.py 环境 1.首先下载整合包&#xff0c;里面有个nltk_data,拿出来…

Jmeter之单接口的性能测试

前言&#xff1a; 服务端的整体性能测试是一个非常复杂的概念&#xff0c;包含生成虚拟用户&#xff0c;模拟并发&#xff0c;分析性能结果等各种技术&#xff0c;期间可能还要解决设计场景、缓存影响、第三方接口mock、IP限制等问题。如何用有限的测试机器&#xff0c;在测试环…

Mysql 连接最近经常报超时

原因 怀疑是某个服务频繁调用mysql操作,导致linux buff/cache 过大 # 通过下列命令查看 free -h解决方案 临时解决方案: 可以通过写入 /proc/sys/vm/drop_caches 来释放缓存。这是一个临时的操作&#xff0c;内核会在需要时再次填充缓存 # 释放缓存 sync; echo 3 > /proc/…

【C语言】详解计算机二级c语言程序题

文章目录 前言资料相关程序题 一&#xff08;字符串&#xff09;程序题 二&#xff08;数组&#xff09;程序题 三&#xff08;基础&#xff09;程序题 四&#xff08;结构体&#xff09;程序题 五&#xff08;结构体&#xff09;程序题 六&#xff08;基础&#xff09; 前言 …

leetcode:491.递增子序列

1.误区&#xff1a;不能直接对数组排序再求解子集&#xff0c;因为那样就改变了原有数组的顺序 2.树形结构&#xff1a;一个一个取数&#xff0c;然后保证是递增序列&#xff0c;且不能重复。&#xff08;数层上不可以重复取&#xff0c;树枝上可以重复取&#xff09;收集的结…

[设计模式Java实现附plantuml源码~行为型]对象间的联动~观察者模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

【大模型 数据增强】IEPILE:基于模式的指令生成解法,提高大模型在信息抽取任务上的性能

IEPILE&#xff1a;基于模式的指令生成解法&#xff0c;提高大模型在信息抽取任务上的性能 提出背景基于模式的指令生成解法效果 提出背景 论文&#xff1a;https://arxiv.org/pdf/2402.14710.pdf 代码&#xff1a;https://github.com/zjunlp/IEPile 2024年02月发布了一个大…

MySQL锁三部曲:临键、间隙与记录的奇妙旅程

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 MySQL锁三部曲&#xff1a;临键、间隙与记录的奇妙旅程 前言临键锁的奥秘间隙锁记录锁 前言 在数据库世界中&#xff0c;锁是维护数据完整性的一种关键机制。而MySQL中的临键锁、间隙锁和记录锁则是锁…

Python 读取创建word文档

本篇文章内容为使用python 读取word文档和创建word文档 读取doc文件 引入类库 示例如下&#xff1a; import win32com import win32com.client import os 读取doc文件 通过得到的doc文件路径调用系统word功能。 打开文件获取其中的文本信息&#xff0c;输出文本信息&#…

彩虹全新 SUP 模板,卡卡云模板修复版

彩虹全新 SUP 模板&#xff0c;卡卡云模板&#xff0c;首页美化&#xff0c;登陆页美化&#xff0c;修复了 PC 端购物车页面显示不正常的问题。下载地址&#xff1a;彩虹全新 SUP 模板.zip 模板截图

[ Python+OpenCV+Mediapipe ] 实现对象识别

一、写在前面 本文所用例子为个人学习的小结&#xff0c;如有不足之处请各位多多海涵&#xff0c;欢迎小伙伴一起学习进步&#xff0c;如果想法可在评论区指出&#xff0c;我会尽快回复您&#xff0c;不胜感激&#xff01; 所公布代码或截图均为运行成功后展示。 二、本文内容…

python 条件语句if else

python 条件语句if else Python条件语句是通过一条或多条语句的执行结果&#xff08;True或者False&#xff09;来决定执行的代码块。 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何非0和非空&#xff08;null&#xff09;值为true&#xff0c;0 或者…

【C语言基础】:操作符详解(一)

文章目录 操作符详解1. 操作符的分类2. 二进制和进制转换2.1 什么是二进制、八进制、十进制、十六进制2.1.1 二进制和进制转换2.1.2 二进制转十进制2.2.3 二进制转八进制2.2.4 二进制转十六进制 3. 源码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符&…

Java学习笔记------继承

继承 Java中提供了一个关键字extends&#xff0c;用这个关键字&#xff0c;我们可以让一个类和另一个类建立继承关系 如图&#xff0c;Student和Teacher类中除了study&#xff08;&#xff09;和teacher&#xff08;&#xff09;两个成员函数不同&#xff0c;其他重复了&…

【摸鱼日常】使用Docker部署2048小游戏

一、本次实践介绍 ​1. 本次实践简介 本次实践部署环境为个人测试环境&#xff0c;快速使用docker部署2048小游戏。 rootWellDone:/home/goodjob# uname -aLinux WellDone 6.5.0-14-generic #14~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Nov 20 18:15:30 UTC 2 x86_64 x86_64…

【深度学习笔记】3_2线性回归的从零实现

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 3.2 线性回归的从零开始实现 在了解了线性回归的背景知识之后&#xff0c;现在我们可以动手实现它了。尽管强大的深度学习框架可以减少大量重复性工作&#xff0c;但若…

【C++精简版回顾】12.友元函数

1.友元函数 1.class class MM { public:MM(int age,string name):age(age),name(name){}friend void print(MM mm); private:int age;string name;void print() {cout << age << "岁的" << name << "喜欢你" << endl;} }; f…

Flutter(一):安装和环境配置、创建Flutter项目

安装和环境配置、创建Flutter项目 Flutter 下载方式1方式2 Flutter 环境配置配置国内镜像站点解压 Flutter将 flutter 添加到系统环境变量中运行 flutter doctor来验证安装 Android Studio下载插件创建项目安装 Android SDK 工具在模拟器上运行 Flutter 下载 方式1 全版本&…

Java基于微信小程序的校园二手物品交易系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…