动态规划的一个初步学习

news2024/11/18 8:32:44

啥叫动态规划

在我们写很多的题目时,常常可以用暴力枚举来写,缺点就是速度太慢了。如果我们用一个数组或者哈希表(虽然我还没学过哈希表)将之前暴力枚举的数据储存起来,当再一次枚举到这个数字的时候就直接调用数组或者哈希表里面的数据,这样就能节省很多时间。所以动态规划就是带数组记忆的递归,所以动态规划也往往叫做记忆化搜索

1.状态转移方程是啥:状态转移方程根据我的理解就是,可以根据前面的一维数组(或者二维数组)推出接下来的数组中的值,优点类似于数学里面的数列里面的递推公式,在动态规划里面比较核心的的就是想出其递推公式,想出来后题目也会变得通透的多。

做动态规划的五步骤

1.dp数组以及下标的含义。
2.递推公式。
3.dp数组的初始化。
4.遍历顺序。
5.打印dp数组

01背包问题

优化前:用一个二维数组来存放数据。优化后:用一个一维数组来存放数据(所以01背包也是由相对固定的模板的)

优化前:二维数组进行存储
首先根据5步曲来,分析一下dp数组的含义:下标为0到i之间的物品(不同的物品有着不同的价值),任取放进容量为j的背包里面,而dp数组的具体值就是放进去这个物品的最大价值。

递推公式不放物品dp[i-1][j];
                      放物品dp[i-1][j-wight[i]]+value[i];(这个value[i]就是i这个物品的价值,同时还要声明一下,这里其实还要做一下判断,看是否有超过背包的最大容量)

最终的模样:dp[i][j]=max(dp[i-1][j],dp[i-1][j-wight[i]]+value[i]);

dp数组的初始化:需要将第一个物品那一行给初始化,其他的都初始化为0.

优化后:使用滚动数组也就是使用一维数组来实现价值最大化   
形象一点就是将这个二维矩阵压缩,或者是将这个贴在一个圆柱上,每次进行到下一个物品的时候就将这个圆柱转一下就切换到下一个物品了。
含义:dp数组里面存放的依然是物品的价值,而下标就是和未优化前的二维数组中的j一样:容量为j的背包所能装的最大价值为dp[j];

递归公式:dp[j]=max(dp[j],dp[j-wight[i]]+value[i]); 这个就是相当于将前一个物品给拷贝过来一份,所以在这里的dp[j]就是相当于前一层的数据。

 列题

过河卒

 做动态规划最重要的就是推出其递推公式,一般很难想到,所以这里建议先在二维数组先写几个数,然后看看这些数之间有没有什么关系(数学归纳法:先写出来几个看看这些数字有啥关系,然后如果找到规律了就直接使用)
(该图来自b站up:LetsLearning)

写几个数字就能发现,在没有马的情况下二维数组中的每一个数的值都是由它的上面和左边加构成,所以通过这里就可以的得到递推公式;a[i][j]=a[i-1][j]+a[i][j-1]; 

接下来就是加上马的干扰,我们先将整个棋盘全部初始化为1(这样做的目的是为了将0行和0列初始化为1,方便接下来的操作),我们用一个方向数组(这个数组里面记载的是马的行走规则,集“日”字型走),用一个for循环将马走到的地方全部初始化为0,这样进行递推的时候就方便进行加,如果加上马的话就需要堆递推进行一点小改动,主要就是体现在第0行和第0列的改动,这个时候第0行和第0列的的递推公式就要改成    a[i][j]=a[i][j-1];    a[i][j]=a[i-1][j]; ,因为马做过的地方的左边和上面都不能走,如果马的这个地方为0,那么后面相加的时候也会为0,就不会对后面的造成影响。
代码如下(中间这些被注释掉的没有必要看,就是用来检查我有没有做对)(对了a数组要开long long类型的,不然有些数据会过不了)

#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll a[35][35];
int n,m;
int x,y;
int dx[9]={0,-1,-2,-2,-1, 1, 2, 2,1};
int dy[9]={0,-2,-1, 1, 2,-2,-1, 1,2};
int main()
{
	//初始化为1
	cin>>n>>m>>x>>y;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=m;j++){
			a[i][j]=1;
		}
	}
	//马的存在
for(int i=0;i<=8;i++){
	int tx=x+dx[i];
	int ty=y+dy[i];
	if(tx<0||tx>n||ty>m||ty<0)
	continue;
	else
	a[tx][ty]=0;
}
//检查二维数组
//	for(int i=0;i<=n;i++){
//		for(int j=0;j<=m;j++)
//		printf("%5d ",a[i][j]);
//		printf("\n");
//	}
//接下来就是递推公式
	for(int i=0;i<=n;i++){
		for(int j=0;j<=m;j++){
			if(i==0&&j==0)
			continue;
			if(a[i][j]==0)//这个点是马走过的,那这里的值就不能走,就应该为0,由于之前我们已经将马走过的地方赋值为0,所以是可以跳过的
			continue;
			if(i==0)
			a[i][j]=a[i][j-1];
			else if(j==0)
			a[i][j]=a[i-1][j];
			else
			a[i][j]=a[i-1][j]+a[i][j-1];
		}
	}
//检查二维数组
//	for(int i=0;i<=n;i++){
//		for(int j=0;j<=m;j++)
//		printf("%5d ",a[i][j]);
//		printf("\n");
//	}
	cout<<a[n][m]<<endl;
	return 0;	
}

守望者的逃离

思路:先讲一遍不用动态规划来写的方法,我么用一个s1和s2分别代表着不用闪现走的路程,和用闪现走的路程,两边同时开弓。每次进行完一次计算都需要将s1和s2进行一次比较将大者的值赋给s1(由于s1是最特殊的,最后我们输出的变量的值也是s1的值)(其实使用动态规划也是使用这样一个思路)其中这里面很巧妙的思路就是使用一个for循环来代表时间的推进还有使用s1,s2两边同时开工,然后这个路程的取值往往都是取最大(我还没学过贪心)。

代码如下:

#include<iostream>
using namespace std;
int m,s,t;
int main()
{
	cin>>m>>s>>t;
	int s1=0,s2=0;
	for(int i=1;i<=t;i++)
	{
		s1+=17;
		if(m>=10){
			s2+=60;
			m-=10;
		}
		else{
			m+=4;
		}
		if(s2>s1)s1=s2;
		if(s1>=s){
			cout<<"Yes"<<endl;
			cout<<i<<endl;
			return 0;
		}
	}
	cout<<"No"<<endl;
	cout<<s1<<endl;
	return 0;
}

接下就是讲解使用dp数组求解:
思路:和上面的思路其实一样,在这里我感觉到动态规划就是要使用前一个数组元素的值来进行求解(及最关键的就是看大问题是否能够被小问题推出,如果已经看出来这一点那么递推公式也就能写出来了),先将dp数组全部用闪现的方式记录每一秒的运动路程。在进行完全部过程后再使用一个for循环来检查就用看是dp[i]大还是dp[i-1]+17大,如果是后者大那么就将这个值赋给dp[i](我怎么感觉有一点01背包的思想在里面).

#include<iostream>
using namespace std;
int dp[500000000];
int main()
{
	int m,s,t;
	cin>>m>>s>>t;
	for(int i=1;i<=t;i++)
	{
		if(m>=10)
		{
			dp[i]=dp[i-1]+60;
			m-=10;
		}
		else
		{
			dp[i]=dp[i-1];
			m+=4;
		}
	}
	for(int i=1;i<=t;i++)
	{
		if(dp[i]<dp[i-1]+17)
		dp[i]=dp[i-1]+17;
		if(dp[i]>=s)
		{
			printf("Yes\n%d",i);
			return 0;
		}
	}
	printf("No\n%d",dp[t]);
	return 0;
}


 

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

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

相关文章

异构计算关键技术之mmap

异构计算关键技术之mmap 一、背景 1. 日志存储系统 case 1&#xff1a;分布式日志存储系统&#xff0c;是一个基于raft协议自研分布式日志存储系统&#xff0c;logstore则是底层存储引擎。 logstore中&#xff0c;使用mmap对数据文件读写。 logstore的存储结构简化如下图&a…

请问半吊子 C++选手该如何深入学习 C++?

请问半吊子 C选手该如何深入学习 C? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff0…

清空队列的方法

注意&#xff1a;C中的队列queue自身不支持clear操作&#xff0c;但双端队列deque是支持clear操作的。 方法一&#xff1a;直接用空的队列对象赋值 代码&#xff1a; queue<int> q; qqueue<int>(); 方法二&#xff1a;遍历出队列 代码&#xff1a; while(!q…

VitePress-14- 配置-titleTemplate 的作用详解

作用描述 1、titleTemplate 是标题的后缀&#xff1b;2、可以自定义标题的后缀&#xff1b;3、可以自定义整个的标题以及后缀&#xff0c;语法如下&#xff1a; titleTemplate: :title 链接符号 自己定义的后缀 【:title】&#xff1a;从页面的第一个 <h1> 标题推断出的…

《计算思维导论》笔记:10.4 关系模型-关系运算

《大学计算机—计算思维导论》&#xff08;战德臣 哈尔滨工业大学&#xff09; 《10.4 关系模型-关系运算》 一、引言 本章介绍数据库的基本数据模型&#xff1a;关系模型-关系运算。 二、什么是关系运算 在数据库理论中&#xff0c;关系运算&#xff08;Relational Operatio…

【开源】SpringBoot框架开发校园疫情防控管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生2.2 老师2.3 学校管理部门 三、系统展示四、核心代码4.1 新增健康情况上报4.2 查询健康咨询4.3 新增离返校申请4.4 查询防疫物资4.5 查询防控宣传数据 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBoot…

Open CASCADE学习|保存为STL文件

STL (Stereolithography) 文件是一种广泛用于3D打印和计算机辅助设计 (CAD) 领域的文件格式。它描述了一个三维模型的表面而不包含颜色、材质或其他非几何信息。STL文件通常用于3D打印过程中&#xff0c;因为它们仅包含构建物体所需的位置信息。 由于STL文件只包含表面信息&am…

YOLOv8算法改进【NO.101】引入最新的损失函数Focaler-IoU

前 言 YOLO算法改进系列出到这&#xff0c;很多朋友问改进如何选择是最佳的&#xff0c;下面我就根据个人多年的写作发文章以及指导发文章的经验来看&#xff0c;按照优先顺序进行排序讲解YOLO算法改进方法的顺序选择。具体有需求的同学可以私信我沟通&#xff1a; 第一…

Days 27 ElfBoard 板 AltiumDesigner 相同电路快速布局布线

在进行设计开发的时候&#xff0c;总会遇到相同的电路&#xff0c;或者模块&#xff0c;这些电路可以使用相同的布局和走线&#xff0c;例如 DC-DC 电源、网口 PHY 电路部分。这类型的电路&#xff0c;我们可以采用AltiumDesigner 中的 Room 进行布局和布线的快速复制&#xff…

c语言数据类型定义错误导致的数据溢出或者死循环

数据溢出问题 #include <stdio.h>/* 数据溢出 */int main() {char i; // 数据表示范围[-128,127] 0xf0 ~ 0x7ffor(i0;i<130;i) // {printf("%d ",i);}return 0; }/* 编译运行上面的程序&#xff0c;你会发现程序陷入了死循环&#xff0c;一直在不断…

多模态知识图谱:感知与认知的交汇

目录 前言1 多模态知识图谱的概念1.1 感知系统与认知系统的连接1.2 信息形式的整合与融合1.3 全面、多维度的认知基础 2 多模态的作用2.1 模态的知识互补2.2 模态实体消歧2.3 模态语义搜索2.4 知识图谱补全2.5 多模态任务增强 3 多模态知识图谱发展历史3.1 初期模态数据整合3.2…

Vue源码系列讲解——虚拟DOM篇【四】(优化更新子节点)

目录 1. 前言 2. 优化策略介绍 3. 新前与旧前 4. 新后与旧后 5. 新后与旧前 6. 新前与旧后 7. 回到源码 8. 总结 1. 前言 在上一篇文章中&#xff0c;我们介绍了当新的VNode与旧的oldVNode都是元素节点并且都包含子节点时&#xff0c;Vue对子节点是 先外层循环newChil…

小游戏和GUI编程(5) | SVG图像格式简介

小游戏和GUI编程(5) | SVG图像格式简介 0. 问题 Q1: SVG 是什么的缩写&#xff1f;Q2: SVG 是一种图像格式吗&#xff1f;Q3: SVG 相对于其他图像格式的优点和缺点是什么&#xff1f;Q4: 哪些工具可以查看 SVG 图像&#xff1f;Q5: SVG 图像格式的规范是怎样的&#xff1f;Q6…

Python贝尔多项式

文章目录 Bell数和Bell多项式第二类Bell多项式 Bell数和Bell多项式 Bell&#xff0c;即所有包含 n n n个对象的有限集合的子集数之和&#xff0c;可通过递推式进行定义 B n ∑ k 0 n − 1 ( n − 1 k ) B k , B 0 1 B_n\sum^{n-1}_{k0}\begin{pmatrix} n-1\\k \end{pmatrix…

基于完全二叉树实现线段树-- [爆竹声中一岁除,线段树下苦踌躇]

文章目录 一.完全二叉树完全二叉树的父子结点引索关系 二.线段树三.基于完全二叉树实现线段树关于线段树的结点数量问题的证明递归建树递归查询区间和递归单点修改线段树模板题 一.完全二叉树 完全二叉树的物理结构是线性表,逻辑结构是二叉树 完全二叉树的父子结点引索关系 …

Javaweb之SpringBootWeb案例之事务管理的详细解析

1. 事务管理 1.1 事务回顾 在数据库阶段我们已学习过事务了&#xff0c;我们讲到&#xff1a; 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位。事务会把所有的操作作为一个整体&#xff0c;一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功&am…

【nginx】starrocks通过nginx实现负载均衡、故障转移与flink运行SR实战

文章目录 一. 通过nginx实现starrocks负载均衡与故障转移1. 架构逻辑与nginx配置2. nginx相关知识&#xff1a;stream模块和http模块2.1. stream模块2.2. http模块 二. 使用flink 消费SR实战1. Expect: 100-continue 问题1.1. Expect: 100-continue的逻辑1.2. 问题分析与解决 2…

微软正在偷走你的浏览记录,Edge浏览器偷疯了

虽然现在 Edge 浏览器相当强大&#xff0c;甚至在某种程度上更符合中国用户的使用体验&#xff1b;但最近新的Edge浏览器推出后一直在使用的用户应该有感受到&#xff0c;原本的冰清玉洁的转校生慢慢小鸡脚藏不住了&#xff0c;广告越来越多&#xff0c;越来越流氓了。 电脑之前…

ubuntu彻底卸载cuda 重新安装cuda

sudo apt-get --purge remove "*cublas*" "*cufft*" "*curand*" \"*cusolver*" "*cusparse*" "*npp*" "*nvjpeg*" "cuda*" "nsight*" cuda10以上 cd /usr/local/cuda-xx.x/bin/ s…

leetcode:51.N皇后

起初会想到暴力&#xff0c;但是N不确定&#xff0c;所以不确定for的嵌套层数&#xff0c;所以我们采用回溯算法。 树形结构&#xff1a; 1.树的深度是第depth层 2.树的宽度是对每一行进行遍历 代码实现&#xff1a; 1.result是三维数组&#xff0c;一个棋盘是二维&#x…