首页 > 其他分享 >动态规划基础

动态规划基础

时间:2024-05-14 22:08:25浏览次数:8  
标签:遍历 int 递推 基础 确定 数组 动态 规划 dp

动态规划基础

某一问题有很多重叠子问题,使用动态规划是最有效的。动态规划中每一个状态是从上一个状态推导出来的。与贪心不同,贪心没有状态推导,从局部中直接选取最优解。

动态规划五部曲:

  1. 确定dp数组以及下标的含义
  2. 确定递推公式
  3. dp数组的初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

example:

leetcode 509

计算斐波那契数列f(n),我们按照上述五部曲的顺序来确定

  1. 确定dp数组以及下标的含义:dp[i]定义为第i个数的斐波那契数值是dp[i]
  2. 确定递推公式:递推公式已经由斐波那契数列的性质给出:dp[i]=dp[i-1]+dp[i-2]
  3. dp数组的初始化:题目中已告知,dp[0]=0,dp[1]=1
  4. 确定遍历顺序:由于第i个数值依赖于第i-1和第i-2个数值,因此遍历顺序是从前到后遍历
  5. 举例推导dp数组: 0 1 1 2 3 5 8 13......
class Solution{
public:
    int fib(int N){
        if(N <= 1){
            return N;
        }
        vector<int> dp(N+1);//确定dp数组
        dp[0]=0;
        dp[1]=1;//初始化递推数组
        for(int i=2;i<=N;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }//遍历顺序
        return dp[N];
    }
};

使用最小花费爬楼梯:

leetcode746

1.确定dp数组以及下标的含义

dp[i]:到达第i阶台阶所花费的最小体力为dp[i]

2.确定递推公式

对于dp[i]的获取,有两个途径,即

dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);

3.初始化dp数组 dp[0]=0 dp[1]=0

4.遍历顺序:从前向后遍历

class Solution{
public:
    int minCostClimbingStairs(vector<int>& cost){
        vector<int> dp(cost.size()+1);
        dp[0]=0;
        dp[1]=0;
        for(int i = 2;i <= cost.size();i++){
            dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        return dp[cost.size()];
    }
}

整数拆分:

leetcode 343

这个题目的难处在于递推公式的确定,我们仍然按照dp的五步方法去做:

  1. 确定dp数组,dp[i]表示对数字i的分拆,得到最大乘积dp[i]
  2. 确定递推公式,由于是将正整数拆分为至少两个整数相乘,考虑到动态规划本就是当前状态由之前的状态递推出,因此我们需要考虑将整数拆分为两个整数相乘或者两个以上的整数相乘,因此:j为从1遍历到i-1,dp[i]从j * (i-j)和 j *dp[i-j]中选择,对j的拆分在遍历过程就实现了。
  3. 初始化dp数组,dp[0]与dp[1]无意义,初始化dp[2]=1即可
  4. 遍历顺序从前到后

代码为

class Solution{
public:
    int integerBreak(int n){
        vector<int> dp(n+1,0);
        dp[2]=1;
        for(int i=3;i<=n;i++){
			for(int j=1;j < i-1;j++){
            //考虑到拆分一个数使其乘积最大,一定是拆分近似相同的子数,即至少拆分为两个近似相同的数字,故此处for可写为for(int j=1;j<=i/2;j++)
                dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]));
            }
        }
        return dp[n];
    }
};

不同路径:

leetcode62

1.确定dp数组含义:dp[i] [j]表示从(0,0)出发,到(i,j)有dp[i] [j]条不同的路径

2.确定递推公式:对于dp[i] [j],只可能是从两个方向移动过来,即

dp[i] [j]=dp [i-1] [j]+dp[i] [j-1]

3.初始化dp数组:显然dp[i] [0]一定为1,而dp[0] [j]也一定为1

class Solution{
public:
    int uniquePaths(int m, int n){
        vector<vector<int>> dp(m,vector<int>(n,0));
        for(int i=0;i<m;i++){
			dp[i][0]=1;
        }
        for(int j=0;j<n;j++){
            dp[0][j]=1;
        }
        for(int i=1;i<m;i++){
			for(int j=1;j<n;j++){
				dp[i][j] = dp[i-1][j]+dp[i][j-1]; 
            }
        }
        return dp[m-1][n-1];
    }
};
//时间复杂度O(m*n)
//空间复杂度O(m*n)

//空间优化:利用一维数组,去逐行更新从(0,0)到达(i,j)的路径数
class Solution{
public:
    int uniquePaths(int m,int n){
        vector<int> dp(n,0);
        for(int i=0;i<n;i++) dp[i]=1;
        for(int j=1;i<m;j++){
			for(int i=0;i<n;i++){
				dp[i] += dp[i-1]//dp[i]=dp[i]+dp[i-1],这就包含了从上方和从左方来的路径和
            }
        }
        return dp[n-1];
    }
};

不同的二叉搜索树

leetcode96

首先定义dp[i],dp[i]表示i个节点组成的搜索二叉树共有dp[i]种

直观来看,容易推导dp[1]=1,dp[2]=2,找到重叠子问题,dp[3],就是 元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量,故有

dp[3]=dp[2] dp[0]+dp[1] * dp[1]+dp[0]dp[2]

class Solution{
public:
    int numTrees(int n){
        vector<int> dp(n+1,0);
        dp[0]=1;
        for(int i = 1;i<=n;i++){
            for(int j=0;j<i;j++){
                dp[i] += dp[j]*dp[i-1-j]
            }
        }
        return dp[n];
    }
};

标签:遍历,int,递推,基础,确定,数组,动态,规划,dp
From: https://www.cnblogs.com/perngfey-note/p/18192358

相关文章

  • 在开发板上显示动态动画
    在开发板上显示动态动画/************************************************************************************filename:bootanimations.c*cauthor:[email protected]*date:2024/05/14*function:显示动态动画*note:none*CopyRigh......
  • 洛谷题单指南-动态规划3-P1070 [NOIP2009 普及组] 道路游戏
    原题链接:https://www.luogu.com.cn/problem/P1070题意解读:1~n个环形机器人工厂,相邻工厂之间的道路是1~n,每个时刻可以从任意工厂购买机器人,走不超过p时间,不同工厂购买机器人花费不同的金币,不同时刻走到不同道路也能得到不同的金币,问一共m时间,最多可以得到多少金币(需减去购买机器人......
  • 统计力学中的概率论基础(二)
    技术背景接上一篇文章,我们继续记录统计力学中的一些基础的概率论知识。这一篇文章主要介绍的是一些常用的概率密度函数的对应参数计算,如期望值、方差等。伯努利分布在离散分布中,最简单的分布为伯努利(Bernoulli)分布,也叫0-1分布。伯努利分布的随机变量就跟抛硬币一样只有两种:0(失......
  • Java面试题 - Java基础
    参考教程【本文参考自以下文章,部分图片及代码片段也取自以下文章,如果构成侵权,请联系我进行修改/删除】【如果构成侵权,请联系我进行修改/删除】【如果构成侵权,请联系我进行修改/删除】【如果构成侵权,请联系我进行修改/删除】自学精灵-首页(本文几乎所有的内容都是自学精灵上......
  • 【反向思维】怎么判断面试者是否有扎实的前端基础?
    前鹅厂前端,待了4年,也算是个前端部分还有点复杂的项目的负责人。在鹅厂面试了几百人,慢慢总结了一下自己的经验,希望对求职的同学有帮助,反向思维及去准备。【技术大厂,前后端可投】我一般就问四个问题,主要还是引导让候选人自个发挥。1,问项目(40分)做过哪些项目,在其中怎么思考的。如果......
  • 热力学基础
    目录目录前言1.热力学第一定律2.理想气体的热容3.理想气体四种过程的计算前言其实是想直接开始写热力学基础的内容的,但是我发现这部分非常需要前置的气体动理论的支撑,因此先写完了气体动理论再开始写热力学基础相关内容。鉴于这部分的内容量比较大,我也不打算再分多篇了,就直......
  • 探索Vue.js:从基础到进阶
    前言随着现代Web应用程序的日益复杂,前端开发框架也在不断演进,为开发者提供更强大、更高效的工具和技术。在这些框架中,Vue.js以其简洁、灵活和响应式的特点而备受青睐。本文将带领读者深入探索Vue.js,从基础概念到进阶技巧,让你全面了解这个令人惊叹的前端开发框架。Vue.js基......
  • 企业组网:构建智慧型网络基础设施,驱动未来商业发展
    随着数字化浪潮的汹涌而至,企业组网已不再是简单的网络连接,而是成为推动企业创新、提升竞争力的重要驱动力。智慧型网络基础设施的构建,不仅为企业内部协作提供了高效平台,更为企业拓展外部市场、应对未来挑战奠定了坚实基础。一、智慧型网络:企业发展的核心引擎在智能化、信息化的......
  • java基础 韩顺平老师的 枚举和注解 自己记的部分笔记
    424,枚举类引出 packagecom.hspedu.enum_;publicclassEnumeration{publicstaticvoidmain(String[]args){//使用Seasonspring=newSeason("春天","温暖");Seasonsummer=newSeason("夏天","炎热&quo......
  • 洛谷题单指南-动态规划3-P1063 [NOIP2006 提高组] 能量项链
    原题链接:https://www.luogu.com.cn/problem/P1063题意解读:本质上是一个环形石子合并问题,计算合并产生的最大能量。解题思路:对于环形DP问题,可以把环拆开,并复制2倍长度,然后用1~n的区间长度去枚举1、状态表示设structnode{inthead,tail}用于表示每一个项链节点,其中有头、尾......