C++:第十四讲动态规划初步

每日C++知识

想要在做C++小游戏里实现等待效果,可以用Sleep。

Sleep函数可以使计算机程序(进程,任务或线程)进入休眠,使其在一段时间内处于非活动状态。

一般需要头文件windows.h。

注意"Sleep"首字母要大写,小括号内参数单位是毫秒。

下面这个示例程序可以帮助你了解一下这个函数:

#include <windows.h>  //需要的头文件int main(void)
{Sleep(1000);    //单位,毫秒 (在VC中Sleep中的第一个英文字符为大写的"S")}

注意

1.用万能头文件不管用了,要包含windows头文件:

#include<windows.h>
2.n可以自由更改,但不要太大,否则容易卡住。

3.Sleep函数一定要大写,否则不管用,会报错。

关于Sleep函数使用
Windows下是大写字母开头的Sleep(),单位为毫秒,linux下面是小写的sleep()。Linux下的sleep()函数是以秒为单位的,sleep(1)就是休眠1毫秒,想实现更短的休眠,linux下有usleep()函数。

记住,Sleep函数中()内只能是数字!

前言

今天带着大家学一个较难的算法——动态规划,简称动规(dp)

动态规划简介

 动态规划相信大家都知道,动态规划算法也是新手在刚接触算法设计时很苦恼的问题,有时候觉得难以理解,但是真正理解之后,就会觉得动态规划其实并没有想象中那么难。

动态规划是一种解决复杂问题的优化策略,它通过对问题进行分而治之的技巧,特别是通过识别并利用子问题间的重叠特性,避免不必要的重复计算,从而达到高效求解的目的。具体来说,动态规划的核心思想是将原问题分解成若干个规模较小的子问题,通过求解这些子问题的最优解来间接获得原问题的最优解。这种方法不仅适用于数学优化问题。

如:

  • 线性动规:拦截导弹、合唱队形、挖地雷、建学校、剑客决斗等;
  • 区域动规:石子合并、加分二叉树、统计单词个数、炮兵布阵等;
  • 树形动规:贪吃的九头龙、二分查找树、聚会的欢乐、数字三角形等;
  • 背包动规:背包问题(easy)、完全背包问题、分组背包问题、二维背包、装箱问题、挤牛奶等;

动态规划的本质,是对问题状态的定义状态转移方程的定义(状态以及状态之间的递推关系)。
动态规划问题一般从以下四个角度考虑

  1. 状态定义
  2. 状态间的转移方程定义
  3. 状态的初始化
  4. 返回结果

例子1 洛谷P1020 导弹拦截

链接——【全网首发】洛谷P1020 [NOIP1999 提高组] 导弹拦截-CSDN博客

AC

//这题满分200!!!
#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =2147483647;
const int MAXN=1e5+3;
int n,t,H[MAXN],F[MAXN];
int main(){while(~scanf("%d",&H[++n])); --n;t=0,memset(F,0,sizeof(F)),F[0]=INF;up(1,n,i){int l=0,r=t+1; while(r-l>1){int m=l+(r-l)/2;if(F[m]>=H[i]) l=m; else r=m;}int x=l+1;  // dp[i]if(x>t) t=x; F[x]=H[i];}printf("%d\n",t);t=0,memset(F,0,sizeof(F)),F[0]=0;up(1,n,i){int l=0,r=t+1; while(r-l>1){int m=l+(r-l)/2;if(F[m]<H[i]) l=m; else r=m;}int x=l+1;if(x>t) t=x; F[x]=H[i];}printf("%d\n",t);return 0;
}

例子2洛谷P1002 过河卒

链接——题目在这里!!!

题目描述

棋盘上 A 点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,A 点 (0,0)、B 点(n,m),同样马的位置坐标是需要给出的。

现在要求你计算出卒从 A 点能够到达 B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

输入格式

一行四个正整数,分别表示 B 点坐标和马的坐标。

输出格式

一个整数,表示所有的路径条数。

输入输出样例

输入 #1

6 6 3 3

输出 #1

6

说明/提示

对于 100% 的数据,1≤n,m≤20,0≤ 马的坐标≤20。

解题思路

矩阵乘法

由于数据很小,n 和 m 的规模只有 20,所以允许一些复杂度较大的做法通过。

如果我们给网格图内的点标号,记从 i 号点到达 j 号点的方法数为 f(i,j),i 号点到 j 号点的边的条数为 ∈{0,1})a(i,j)(a(i,j)∈{0,1}),那么枚举经过的点 k,则有 i 点到 j 点的方法数 =i 点到k 点的方法数 ×k 点到 j 点的方法数,形式化的讲,f(i,j)=f(i,k)⋅a(k,j)。

我们惊奇的发现,这就是矩阵乘法的定义。

因此,我们连接所有互相可达的点,进行矩阵快速幂即可。

有一种特殊情况:如果起点或终点离马的位置太近,那么上面的分类讨论的第 4 种和第 5 种情况就会出现问题——可能起点或终点本来就在马的攻击范围内。

所以,遇到这种情况别忘记特判。

AC

#include<iostream>
using namespace std;
const int N = 35;
int n, m, x, y;
long long dp[N][N];   
bool vis[N][N];
int X[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int Y[8] = {-1, -2, -2, -1, 1, 2, 2, 1};  
int main()
{cin >> n >> m >> x >> y;dp[2][1] = 1;vis[x+2][y+2] = 1;for (int i = 0; i < 8; i ++)vis[x+X[i]+2][y+Y[i]+2] = 1;  for (int i = 2; i <= n+2; i ++)for (int j = 2; j <= m+2; j ++) {if (vis[i][j])continue;  dp[i][j] = dp[i-1][j] + dp[i][j-1];}cout << dp[n+2][m+2];return 0;
}

例子3洛谷P1216 数字三角形 

链接——题目在这里!!!

题目描述

观察下面的数字金字塔。

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

在上面的样例中,从 7→3→8→7→5的路径产生了最大权值。

输入格式

第一个行一个正整数 r ,表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

输出格式

单独的一行,包含那个可能得到的最大的和。

输入输出样例

输入 #1

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5 

输出 #1

30

说明/提示

【数据范围】
对于100% 的数据,1≤r≤1000,所有输入在 [0,100] 范围内。

解题思路

分析题干,发现从上面往下一步步走很麻烦,直接搜索肯定超时。所以,逆向求解

看样例分析:

        7 3   8 8   1   0 2   7   4   4 
4   5   2   6   5

若从倒数第二排的‘2’开始走,只有2个选择,往左下方和右下方。

往左下方是‘4’,得到的最终值为6,往右下方是‘5’,得到的最终值是7.这时当然选择右下方。

我们就将‘2’改写成2+5=7。 再次考虑倒数第二排的7,

同理,应选择左下,得到最终值是12。还是将‘7’改写成5+7=12。

依次类推则倒数第二排变为:

7 12 10 10 

原数字三角形变为:

        7 3   8 8   1   0 7   12  10  10 
4   5    2    6   5

这时再考虑第三行第一个。有两种选择:左下和右下。

假设走左下方,由于这时左下的值已经是从左下开始走到底的最优值,我们不需要在选择下一步怎么走,直接加上左下的值即可。

同理,走右下时,直接加上右下的值即可。因为此时右下的值已经是从右下走到底的最优值,不需要选择了。

再比较走两条路的值,右边的值更大,选择右边的值。则第三行的第一个值更新为8+12=20。

以此类推,得到下面的数字三角形:

        7 3   8 20  13  10 7   12  10  10 
4   5    2    6   5

同理,更新第二排,有:

           7 23   21 20   13   10 7   12   10  10 
4    5    2    6    5 

最后一个了,有:

           30 23   21 20   13   10 7   12   10  10 
4    5    2    6    5

AC

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N=1e5+5;
int m[1005][1005];
int dp[1005];
int main()
{ios_base::sync_with_stdio(NULL);cin.tie(NULL),cout.tie(NULL);int n;cin>>n;for(int i=0;i<n;i++)for(int j=0;j<i+1;j++)cin>>m[i][j];for(int i=0;i<n;i++)dp[i]=m[n-1][i];for(int i=n-2;i>=0;i--){for(int j=0;j<i+1;j++)dp[j]=max(m[i][j]+dp[j],m[i][j]+dp[j+1]);}cout<<dp[0]<<endl;return 0;
}

课后小练习P1049 装箱问题

链接——题目在这里!!!

题目描述

有一个箱子容量为V,同时有n 个物品,每个物品有一个体积。

现在从n 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小。输出这个最小值。

输入格式

第一行共一个整数 V,表示箱子容量。

第二行共一个整数 n,表示物品总数。

接下来 n 行,每行有一个正整数,表示第 i 个物品的体积。

输出格式

共一行一个整数,表示箱子最小剩余空间。

输入输出样例

输入 #1

24
6
8
3
12
7
9
7

输出 #1

0

说明/提示

对于 100%数据,满足 n≤30,1≤V≤20000。

解题思路

这道题看似是搜索,但是可以用背包做。

题目要求求出最小的剩余空间,也就是要求出最大的可装重量

这样,我们可以将一个物体的重量当作它的价值,进而将题目转变为一个基本的01背包问题:

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)和一个价值(等于体积)。

要求n个物品中,任取若干个装入箱内,使总价值最大。

对于每一个物体,都有两种状态:装 与不装

那么,对于任意重量m的最大价值 f (m) = max ( f ( m - w[i] ) + w[i], f (m) )(w为重量(即价值))

其中,f ( m - w[i] ) 指在装了物品i后,箱子的剩余容量能装的最大重量

f ( m - w[i] ) + w[i] 指在在装了物品i后,箱子能装的最大重量

AC

#include<bits/stdc++.h>
using namespace std;
bool b[20005];
int n, v;
int a[35];
int main(){cin >> v >> n;for (int i = 1; i <= n; i++) cin >> a[i];b[0] = 1;for (int i = 1; i <= n; i++)  for (int j = v; j >= a[i]; j--)if (b[j - a[i]]) b[j] = 1;for (int i = v; i >= 1; i--)if (b[i]){cout << v - i;break;}	return 0;
}

思考题洛谷P1091 合唱队形

链接——题目在这里!!!

解题思路

本人觉得这题是很不错的,虽然难度不高。首先,我们要想出列最少,那么就想要留下的最多。很容易想的最长升,但是,这个序列是一个中间高,两头底的序列,最长升只能处理出单调性的序列。我们先看从T1到Ti这一段单调递增的序列,再看Ti到TK这一段单调递减的序列,那么问题就解决了。先从1到n求一趟最长升,然后从n到1也求一趟,最后枚举中间的Ti,然后从众多Ti中挑个大的。

AC

#include<iostream>
#include<cstdio>
using namespace std;
int g[105],f[105],a[105],s[105];
int main()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];f[i]=1;g[i]=1;}for(int i=n-1;i>=1;i--){for(int j=i+1;j<=n;j++){if(a[i]>a[j]&&f[i]<=f[j]+1){f[i]=f[j]+1;}}}for(int i=2;i<=n;i++){for(int j=1;j<i;j++){if(a[i]>a[j]&&g[i]<=g[j]+1){g[i]=g[j]+1;}}}int maxx=0;for(int i=1;i<=n;i++){s[i]=f[i]+g[i]-1;if(s[i]>maxx){maxx=s[i];}}cout<<n-maxx;
}

结尾

希望大家多多关注!!!

本篇文章共5996字,如果你能支持一下我,我十分感谢!!!

如果有人想在洛谷上做题,可以点下方链接:

https://www.luogu.com.cn/

如果你喜欢或想了解一下其他的算法,可以看看以下这些:

题目详解系列(部分):

【万题详解】洛谷P1252 马拉松接力赛-CSDN博客

【万题详解】洛谷P1359 租用游艇-CSDN博客

【百题详解】洛谷P8508 做不完的作业-CSDN博客

【万题详解1】洛谷P1230 智力大冲浪-CSDN博客

【全网首发】洛谷贪心题解集合-CSDN博客

洛谷二分题集(3题)-CSDN博客

游戏系列:

C++:史上最坑小游戏-CSDN博客

 C++:自创小游戏-CSDN博客

C++:下雪-CSDN博客

C++讲解系列(算法):

C++:第十二讲DFS深搜(二)_c++匿名函数dfs-CSDN博客

 C++:第十一讲DFS深搜-CSDN博客

C++:第十讲二分查找-CSDN博客

前缀和与差分:

C++:第九讲前缀和与差分-CSDN博客

贪心:

C++:第八讲贪心算法1-CSDN博客

C++讲解系列(基础入门):

排序:

C++:第七讲冒泡排序-CSDN博客

函数:

C++第6讲max和min函数_c++ min函数-CSDN博客

C++第五讲函数初步-CSDN博客

for循环&数组:

C++第四讲for循环及数组-CSDN博客

if语句&else语句及运算:

C++第三讲:C++中的逻辑运算符及if else语句-CSDN博客

基础:

C++第二讲输入与输出-CSDN博客

C++第一讲认识C++编译器-CSDN博客

欢迎收看,希望大家能三连!

最后认识一下,我是爱编程的喷火龙廖,我们有缘再见!

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

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

相关文章

ppt背景图片怎么设置?让你的演示更加出彩!

PowerPoint是一款广泛应用于演示文稿制作的软件&#xff0c;而背景图片是演示文稿中不可或缺的一部分。一个好的背景图片能够提升演示文稿的整体效果&#xff0c;使观众更加关注你的演示内容。可是ppt背景图片怎么设置呢&#xff1f;本文将介绍ppt背景图片设置的三个方法&#…

Spring-boot项目+Rancher6.3部署+Nacos配置中心+Rureka注册中心+Harbor镜像仓库+NFS存储

目录 一、项目概述二、环境三、部署流程3.1 Harbor部署3.1.1 docker安装3.1.2 docker-compose安装3.1.3 安装证书3.1.4 Harbor下载配置安装 3.2 NFS存储搭建3.3 Rancher平台配置3.3.1 NFS存储相关配置3.3.2 Harbor相关配置3.3.3 Nacos部署及相关配置3.3.4 工作负载deployment配…

ubuntu20.04 安装ROS2 记录

主要参考B站古月居的ROS2入门21讲 和 以下链接&#xff08;基本和视频上一致&#xff09; ubuntu20.04安装ROS2 详细教程_ubuntu20.04 ros2-CSDN博客 但是中间有些需要注意的地方&#xff0c; 1&#xff0c;添加源 步骤中提到 sudo curl -sSL https://raw.githubuserconten…

Redis冲冲冲——缓存三兄弟:缓存击穿、穿透、雪崩

目录 引出缓存击穿缓存穿透缓存雪崩 总结 引出 谈谈redis的击穿、穿透、雪崩。 缓存击穿 缓存击穿&#xff1a;redis中没有&#xff0c;但是数据库有 顺序&#xff1a;先查缓存&#xff0c;判断缓存是否存在&#xff1b;如果缓存存在&#xff0c;直接返回数据&#xff1b;如果…

【前端素材】bootstrap3 实现地产置业公司source网页设计

一、需求分析 地产置业公司的网页通常是该公司的官方网站&#xff0c;旨在向访问者提供相关信息和服务。这些网页通常具有以下功能&#xff1a; 公司介绍&#xff1a;网页通常包含有关公司背景、历史、核心价值观和使命等方面的信息。此部分帮助访问者了解公司的身份和目标。 …

人工视觉仍然需要图像采集卡

最初&#xff0c;图像采集卡被用作模拟视频数字转换器和图像缓冲器&#xff0c;但如今它们能够执行复杂的任务&#xff0c;例如图像处理。图像采集卡的设计不断发展&#xff0c;旨在提高系统性能并减少计算机处理需求。 除了图像采集之外&#xff0c;图像采集卡还执行机器视觉…

芯片跨时钟域设计(二)

芯片培训(真实项目)介绍&#xff1a; 低功耗景芯SoC前端、中端、后端全流程实战培训(火爆订购中) DDR4/3项目实战培训 ARM Cortex-A72处理器12nm PR实战培训 ARM Cortex-A72处理器12nm DFT实战培训 ARM Cortex-A7处理器28nm PR实战培训(火爆价格战) RISC-V MCU 40nm全芯片…

抽象类(Java)、模板方法设计模式

一、概念 在Java中有abstract关键字&#xff0c;就是抽象的意思&#xff0c;可用来修饰类和成员方法。 用abstract来修饰类&#xff0c;那这个类就是抽象类&#xff1b;修饰方法&#xff0c;那这个方法就是抽象方法。 修饰符 abstract class 类名{修饰符 abstract 返回值类型…

走进水稻种植教学基地可视化:科技与农业知识的完美结合

随着科技的不断发展&#xff0c;农业领域也在不断创新和进步。水稻种植教学基地可视化系统是一种基于现代信息技术手段的教学方式&#xff0c;通过虚拟现实、3D建模等技术&#xff0c;将水稻种植的全过程进行模拟和展示。这种教学方式打破了传统农业教学的局限性&#xff0c;使…

Springboot+vue的健身房管理系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的健身房管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的健身房管理系统&#xff0c;采用M&#xff08;model&#xf…

知识点积累系列(一)golang语言篇【持续更新】

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 知识点积累 系列文章的第一篇&#xff0c;记录golang语言相关的知识点 1.结构体的mapstructure是什么 mapstructure:"default" mapstructure是一个Go语言的库&#xff0c;用于将一个map中的值映射到…

STM32读取MPU6050数据并通过角度值控制舵机运动(STM32、GY-521 MPU6050、SG90舵机、MG946舵机)

通过STM32F103C8T6读取MPU6050数据控制舵机运动&#xff08;STM32、GY-521 MPU6050、SG90舵机、MG946舵机&#xff09; 最终现象一、MPU6050数据读取二、舵机控制原理①什么是PWM&#xff1f;②STM32F103C8T6如何生成PWM&#xff1f;③控制舵机需要什么样的PWM波&#xff1f; 三…

【Go】Channel底层实现 ②

文章目录 channel底层实现channel发送、接收数据有缓冲 channelchannel 先写再读channel 先读再写(when the receiver comes first) 无缓冲channelchannel存在3种状态&#xff1a; channel底层实现 // channel 类型定义 type hchan struct {// channel 中的元素数量, lenqcoun…

【排序算法】C语言实现随机快排,巨详细讲解

文章目录 &#x1f680;前言&#x1f680;快排的核心过程partition&#xff08;划分过程&#xff09;&#x1f680;快排1.0&#x1f680;随机快速排序&#x1f680;稳定性 &#x1f680;前言 铁子们好啊&#xff01;继续我们排序算法今天要讲的是快排&#xff0c;通常大家所说…

房产信息网源码,房产系统,二手房小程序源码,租房小程序系统楼盘系统房产经纪人系统

房产门户系统、多城市房产网、房产小程序 房产网系统、地方房产门户信息网 带im即时通讯聊天 二手房 租房 楼盘 置业顾问 经纪人 腾房云房产网 分为单城市版本 和多城市版本 多城市 自动定位当前城市 每个分站对应独立管理员分站管理 thinkphpuniapp 独立开源

微信开发者工具 git 拉取 failed invalid authentication scheme

微信开发者工具 git 拉取 failed invalid authentication scheme 拉取代码时报错,无效身份认证 解决方案: 1.检查git地址是否正常 2.检查git用户名密码是否正确

uniapp多格式文件选择(APP,H5)

uniapp多格式文件选择&#xff08;APP&#xff0c;H5&#xff09; 背景实现代码实现运行结果注意事项 尾巴 背景 从手机选择文件进行上传是移动端很常见的需求&#xff0c;在原生开发时由于平台专一性很容易实现。但是用uniapp开发官方提供的API在APP平台只能选择图片和视频&a…

使用visual studio写一个简单的c语言程序

官网下载visual studio&#xff0c;社区版免费的 https://visualstudio.microsoft.com/zh-hans/ 下载好以后选择自己的需求进行安装&#xff0c;我选择了两个&#xff0c;剩下的是默认。 创建文件&#xff1a;

K8s 安装部署-Master和Minion(Node)

K8s 安装部署-Master和Minion(Node) 操作系统版本&#xff1a;CentOS 7.4 Master &#xff1a;172.20.26.167 Minion-1&#xff1a;172.20.26.198 Minion-2&#xff1a;172.20.26.210&#xff08;后增加节点&#xff09; ETCD&#xff1a;172.20.27.218 先安装部署ETCD y…

第16章_网络编程(网络通信要素,TCP与UDP协议,网络编程API,TCP网络编程,UDP网络编程,URL编程)

文章目录 第16章_网络编程本章专题与脉络1. 网络编程概述1.1 软件架构1.2 网络基础 2. 网络通信要素2.1 如何实现网络中的主机互相通信2.2 通信要素一&#xff1a;IP地址和域名2.2.1 IP地址2.2.2 域名 2.3 通信要素二&#xff1a;端口号2.4 通信要素三&#xff1a;网络通信协议…