初级算法-动态规划

文章目录

        • 爬楼梯
          • 题意:
          • 解:
          • 代码:
        • 买卖股票的最佳时机
          • 题意:
          • 解:
          • 代码:
        • 最大子序和
          • 题意:
          • 解:
          • 代码:
        • 打家劫舍
          • 题意:
          • 解:
          • 代码:

爬楼梯

题意:

从0开始,每次+1或者+2,求和为n有多少种可能

解:

DP[i]表示到达i能有几种可能

初始状态DP[0]=1

递推公式DP[i]=DP[i-1]+DP[i-2]

因为每次只能+1或+2,所以而状态i-1一定不会影响(改变)i-2所以正向遍历即可(i-2会改变i-1

代码:
#include<iostream>
#include<cstring>
using namespace std;
constexpr int N=50;
int climbStairs(int n)
{int dp[N];memset(dp,0,sizeof dp);dp[0]=1;for(int i=0;i<n;i++){dp[i+1]+=dp[i];dp[i+2]+=dp[i];}return dp[n]; 
}
int main()
{int ans;cin>>ans;ans=climbStairs(ans);cout<<ans<<endl;
}

买卖股票的最佳时机

题意:

预知股票价格,求一次买入+一次卖出能赚的最大金额

解:

DP[i]表示第i天前的最低价格

对于第Day天的价格我们要找Day之前最便宜的股票买,所以递推式DP[day]=min{ Day[0,Day) }

而初始状态第一天之前的价格我们设置成>=prices[0]即可,因为这时候是不赚钱甚至亏钱的,保持答案0

那么对于每一天day我们先用今天的价格prices[day]-DP[day-1]获取今天的最高利润,然后DP[day]=min(prices[day],DP[day-1])更新这一天之前(包含)的最低价格

由于是一次买入一次卖出,所以取最高值,并且DP[i]只和DP[i-1]有关,而这两者都是基于prices[i]计算/更新,

所以用一个变量aftre充当DP[i-1]即可

代码:
#include<bits/stdc++.h>
using namespace std;
int maxProfit(vector<int>& prices)
{int lg=prices.size();int after=INT_MAX,ans=0;for(auto &price:prices){ans=max(ans,price-after);after=min(after,price);}return ans;
}
int main()
{vector<int> prices;int temp;while(cin>>temp){prices.push_back(temp); }int ans=maxProfit(prices);cout<<ans<<endl;return 0;
}

最大子序和

题意:

如题。子数组 是数组中的一个连续部分。

解:

主要说一下分治法

思路就是一个区间[l,r]内的最大子数组要么处于[l,mid]要么处于[mid+1,r],或者处于[l,r],虽然很像废话,但是对计算机来说不一样,由于要找子数组,所以要保持连续性,所以当这个区间内的最大子数组在[l,r]情况下,一定是包含[l,mid]的右边和[mid+1,r]的左边

那么对于一个区间,我们维护它的左起最大子数组、右起最大子数组还有无条件子数组以及区间和

分别有什么作用呢?对于最小子区间[t,t]这四个数值都是nums[t]

而对于一个父区间,它的左起子数组 是max [l,mid]->left ,[mid+1,r]->left+[l,mid]->sum,为了保持连续性,只有两种可能,要么是左子区间的 左起最大子数组,要么是整个左子区间加上右子区间的 左起最大子数组

对于右起最大子数组也是一样的,保留右起的连续性;

还有一种无条件子数组,指的是不一定包含左起点或者右起点的最大子数组,由于这可能是答案的一部分,所以要对它进行保留和计算,计算方式是<左子区间的右连上右子区间的左>和两个子区间的无条件子数组中取最大值

代码:
#include<bits/stdc++.h>
using namespace std;
struct ITEM
{int l,r,m,sum;  
};
ITEM query(int l,int r,vector<int>& nums)
{//cout<<"l:"<<l<<"r"<<r<<endl;if(l==r) return {nums[l],nums[l],nums[l],nums[l]};int mid=(l+r)>>1;ITEM item1=query(l,mid,nums);ITEM item2=query(mid+1,r,nums);ITEM ret;ret.l=max(item1.l,item1.sum+item2.l);ret.r=max(item2.r,item2.sum+item1.r);ret.m=max(item2.l+item1.r,max(item1.m,item2.m));ret.sum=item1.sum+item2.sum;return ret;  
}
int maxSubArray(vector<int>& nums)//分治法 
{int lg=nums.size();ITEM ret=query(0,lg-1,nums);int ans=max(ret.l,max(ret.r,ret.m));return ans;
}
/*
int maxSubArray(vector<int>& nums)//遍历法O(n) 
{int lg=nums.size(),temp=0,ans=nums[0];for(auto &num:nums){temp+=num;ans=max(ans,temp);if(temp<0) temp=0;}return ans;
}*/
int main()
{vector<int> nums;int num;while(cin>>num) nums.push_back(num);int ans=maxSubArray(nums);cout<<ans<<endl;return 0;
}

打家劫舍

题意:

一个非负整数数组,从中选择数字字求最大和,要求不能选择连续的数字

解:

先将问题想的复杂一点,DP[0][i]表示第i个数字不选择时区间[0,i]的最大和,DP[1][i]表示选择第i个数字,这样可轻松推出dp[0][i]=max(dp[0][i-1],dp[1][i-1])dp[1][i]=max(nums[i]+dp[0][i-1],dp[0][i-1])

但是我们再想一想,DP[i]表示第i个数字(不管选不选)时区间[0,i]的最大和,那么由于不知道i是否被选上,所以我们的递推式只能变成DP[i]=max(DP[i-1],DP[i-2]+nums[i]),这样是否合理呢?

是合理的因为DP[i]不管选没选择这个递推式都不会选择连续的数字,只要初始状态合理就行,初始状态设置DP[0]=nums[0] DP[1]=max(nums[0],nums[1]),从第一步DP[2]的计算我们就可以看出,无论如何我们都不会计算DP[2]包含nums[1]+nums[2],同时由于这个递推式只需要三个变量,所以可以用滚动变量解决

代码:
#include<bits/stdc++.h>
using namespace std;
int rob(vector<int>& nums)//J2
{int lg=nums.size();if(lg==1) return nums[0];int temp1=nums[0],temp2=max(nums[0],nums[1]);for(int i=2;i<lg;i++){int temp=temp2;temp2=max(temp2,temp1+nums[i]);temp1=temp;}return temp2;
}
/*
int rob(vector<int>& nums)//J1
{int lg=nums.size();vector<vector<int>>dp(2,vector<int>(lg));dp[1][0]=nums[0];for(int i=1;i<lg;i++){dp[0][i]=max(dp[0][i-1],dp[1][i-1]);dp[1][i]=max(nums[i]+dp[0][i-1],dp[0][i-1]);}return max(dp[0][lg-1],dp[1][lg-1]);
}*/
int main()
{vector<int> nums;int num;while(cin>>num) nums.push_back(num);int ans=rob(nums);cout<<ans<<endl;return 0;
}

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

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

相关文章

Mysql的锁

加锁的目的 对数据加锁是为了解决事务的隔离性问题&#xff0c;让事务之前相互不影响&#xff0c;每个事务进行操作的时候都必须先加上一把锁&#xff0c;防止其他事务同时操作数据。 事务的属性 &#xff08;ACID&#xff09; 原子性 一致性 隔离性 持久性 事务的隔离级别 锁…

(3)Gymnasium--CartPole的测试基于DQN

1、使用Pytorch基于DQN的实现 1.1 主要参考 (1)推荐pytorch官方的教程 Reinforcement Learning (DQN) Tutorial — PyTorch Tutorials 2.0.1cu117 documentation (2) Pytorch 深度强化学习 – CartPole问题|极客笔记 2.2 pytorch官方的教程原理 待续&#xff0c;这两天时…

bug篇之基于docker安装nacos(2.1.1)使用dubbo连接不上的问题

说明&#xff1a;首先我的nacos安装是2.1.1版本&#xff0c;请注意版本问题。另外启动时用dubbo的话必须先启动服务提供者再启动服务使用者&#xff0c;否则会报错&#xff0c;同时也必须开放三个端口&#xff1a;8848&#xff0c;9848&#xff0c;9849 java.lang.IllegalStat…

Python入门【__init__ 构造方法和 __new__ 方法、类对象、类属性、类方法、静态方法、内存分析实例对象和类对象创建过程(重要)】(十四)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

防止表单的重复提交

思想 打开页面时&#xff0c;生成一个token&#xff0c;将这个token保存到Session中&#xff0c;在表单中提供一个隐藏域&#xff0c;设置其值为每1步中生成的token在处理表单的Servlet中&#xff0c;获取表单隐藏域中的token与Session中的token进行比较&#xff0c;比较完之后…

设计模式——简单工厂模式

1 概述 将创造对象的工作交给一个单独的类来实现 &#xff0c;这个单独的类就是工厂。 2 实现 假设要做一个计算器的需求&#xff0c;通常我们想到的是这样写&#xff1a; package com.example.easyfactory;import java.util.Scanner;public class Demo1 {public static vo…

spring学习笔记十五

Spring整合Mybatis 1、导入pom坐标 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency><!-- https://mvnrepository.com/artifact/c3p0/c3p0 --><!…

SpringBoot Jackson 日期格式化统一配置

目录 1.在全局配置文件配置 2.通过JavaBean方式配置 1.在全局配置文件配置 spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8 该配置方式仅支持 Date 类型的日期格式化&#xff0c;不支持LocalDate 及 LocalDateTime 的格式化。 2.通过JavaBean方式配置 …

[C++] 类与对象(上)

目录 1、前言 2、类的引入 3、类的定义 3.1 类的两种定义方式 4、类的访问限定符 5、类的作用域 6、类的实例化 7、类对象模型 7.1 内存对齐规则 7.1 类对象的存储方式 8、this指针 8.1 this指针的特性 8.2 this指针是否可以为空 1、前言 C语言是面向过程的&#…

DUBBO服务多网卡,服务调用失败

如果服务器是多网卡的&#xff0c;比如安装了docker&#xff0c;有一个docker虚拟网卡&#xff0c;一个实体网卡eth0&#xff0c;当我们运行springboot应用后&#xff0c;dubbo注入到zk的地址是 docker虚拟网卡的地址172网段&#xff0c;而不是实际内网地址192网段&#xff0c;…

类的封装和包(JAVA)

封装 所有的OOP语言都会有三个特征&#xff1a; 封装&#xff1b;继承&#xff1b;多态。 本篇文章会为大家带来有关封装的知识。 在我们日常生活中可以看到电视就只有那么几个按键&#xff08;开关&#xff0c;菜单……&#xff09;和一些接口&#xff0c;而而我们通过这些东…

【计算机视觉|人脸建模】SOFA:基于风格、由单一示例的2D关键点驱动的3D面部动画

本系列博文为深度学习/计算机视觉论文笔记&#xff0c;转载请注明出处 标题&#xff1a;SOFA: Style-based One-shot 3D Facial Animation Driven by 2D landmarks 链接&#xff1a;SOFA: Style-based One-shot 3D Facial Animation Driven by 2D landmarks | Proceedings of …

jmeter压力测试指标解释

目录 RT(response time) Throughput 吞吐量 并发用户数 QPS (query per seconds) TPS (transition per seconds) PV和UV 聚合报告&#xff1a; RT(response time) 什么是RT? RT就是指系统在接收到请求和做出相应这段时间跨度 但是值得一提的是RT的值越高,并不真的就能…

什么是云原生和 CNCF?

一、CNCF简介 CNCF&#xff1a;全称Cloud Native Computing Foundation&#xff08;云原生计算基金会&#xff09;&#xff0c;成立于 2015 年 12 月 11 日&#xff0c;是一个开源软件基金会&#xff0c;它致力于云原生&#xff08;Cloud Native&#xff09;技术的普及和可持续…

Klipper seria.c 文件代码分析

一. 前言 Klipper 底层硬件的串口模块程序写的是否正确是决定下位机与上位机能否正常通信的前提&#xff0c;如果这个文件的驱动没写好&#xff0c;那上位机控制下位机就无从谈起&#xff0c;更无法通过上位机去验证下位机程序的正确性。 本篇博文将详细解析 Klipper src 文件夹…

Android—Monkey用法

文章目录 Monkey知识 Monkey知识 介绍 Monkey是Android中的一个命令行工具&#xff0c;可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等)&#xff0c;实现对正在开发的应用程序进行压力测试。Monkey测试是一种为了测试软…

SQL server 简介

SQL server 简介 学习目的 SQL Server 是由微软公司开发的一种关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;用于存储和检索数据。它提供了一个可扩展的、安全的和可靠的数据存储和管理解决方案。 SQL Server 主要用于构建企业级应用程序&#xff0c;支持…

js笔记总结

prototype 属性的作用 JavaScript 规定&#xff0c;每个函数都有一个prototype属性&#xff0c;指向一个对象。 function f() {} typeof f.prototype // "object" ​ 上面代码中&#xff0c;函数f默认具有prototype属性&#xff0c;指向一个对象。 对于普通函数来…

809协议

809协议 目录概述需求&#xff1a; 设计思路实现思路分析1.809协议数据流——链路管理类 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,…

在idea中添加try/catch的快捷键

在idea中添加try/catch的快捷键 在idea中添加try/catch的快捷键 ctrlaltt 选中想被try/catch包围的语句&#xff0c;同时按下ctrlaltt&#xff0c; 出现下图 选择try/catch即可。