• 动态规划-1


    70. 爬楼梯【简易】

    假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

    每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

    注意:给定 n 是一个正整数。

    示例 1:

    输入: 2
    输出: 2
    解释: 有两种方法可以爬到楼顶。
    1.  1 阶 + 1 阶
    2.  2 阶

    示例 2:

    输入: 3
    输出: 3
    解释: 有三种方法可以爬到楼顶。
    1.  1 阶 + 1 阶 + 1 阶
    2.  1 阶 + 2 阶
    3.  2 阶 + 1 阶

    思路:

    问题拆分:到达第n个台阶有两种方法:1.从【n-1】迈一步。2.从【n-2】迈两步。 

    用dp[i]记录到达第i个台阶的方法数,从而得到递推公式:dp[n]=dp[n-1]+dp[n-2] 。

    class Solution {
    public:
        int climbStairs(int n) {
            if(n<3)return n;
            else{
            int dp[2]={1,2},t=0;
            for(int i=3;i<=n;i++){
                t=dp[1];
                dp[1]=dp[0]+dp[1];
                dp[0]=t;
            }
            return dp[1];
            }
        }
    };
    

      

    53. 最大子序和【简易】

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

    示例:

    输入: [-2,1,-3,4,-1,2,1,-5,4],
    输出: 6
    解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
    

    思路:

    问题拆分:下标【x】到【y】的子数组,判断加上【y+1】项后,与第【y+1】项相比,是大还是小。

        1.如果前者大,那么加上[y+1]项肯定能组成更大。

        2.如果后者大,那么就从[y+1]项开始,重新组成一个最大子数组。

    dp[i]定义为以i结尾的某个子数组的最大值,递推公式为:dp[i]=max(dp[i-1]+nums[i],nums[i])

    class Solution {
    public:
        int maxSubArray(vector<int>& nums) {
            int res=nums[0];
            int len=nums.size();
            int dp[len+1];
            dp[0]=nums[0];
            for(int i=1;i<len;i++){
                dp[i]=max(dp[i-1]+nums[i],nums[i]);
                res=max(res,dp[i]);
            }
            return res;
        }
    };

    给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

    例如,给定三角形:

    [
         [2],
        [3,4],
       [6,5,7],
      [4,1,8,3]
    ]
    

    自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

    说明:

    如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。

    思路:用dp[i][j]代表走到(i-1)行,(j-1)列的最小值。它是由上边一行推出来的。

    递推公式为:1.若为第一个元素:dp[i][j]=dp[i-1][j]+triangle[i][j]

          2.若为最后一个元素:dp[i][j]=dp[i-1][j-1]+triangle[i][j]

          3.若为中间元素:dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+triangle[i][j]

    最后再遍历一下最后一行的dp数组,求得最小值。

    class Solution {
    public:
        int minimumTotal(vector<vector<int>>& triangle) {
            int m=triangle.size();
            int dp[m+1][m+1];
            dp[0][0]=triangle[0][0];
            for(int i=1;i<m;i++){
                for(int j=0;j<i+1;j++){
                    if(j==0){dp[i][j]=dp[i-1][j]+triangle[i][j];}
                    else if(j==i){dp[i][j]=dp[i-1][j-1]+triangle[i][j];}
                    else { dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+triangle[i][j];}
                }
            }
            int res=dp[m-1][0];
            // for(int i=0;i<m;i++)
            // for(int j=0;j<=i;j++)
            // cout<<dp[i][j]<<',';
            for(int j=1;j<m;j++){
                res=min(res,dp[m-1][j]);
            }
            return res;
        }
    };
    

      

  • 相关阅读:
    JetBrains全系列破解
    BZOJ 4817: [Sdoi2017]树点涂色 LCT + DFS序 + 线段树
    LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度 LCT + SAM + 线段树
    Uoj 52. 【UR #4】元旦激光炮 交互题
    Uoj #218. 【UNR #1】火车管理 可持久化线段树+思维
    luoguP3979 遥远的国度 LCT + multiset维护子树信息
    BZOJ 4999: This Problem Is Too Simple! DFS序 + LCA + 树状数组 + 离线
    BZOJ 1787: [Ahoi2008]Meet 紧急集合
    BZOJ 2959: 长跑 LCT + 并查集 + 点双
    BZOJ 4259: 残缺的字符串 FFT
  • 原文地址:https://www.cnblogs.com/52dxer/p/12837092.html
Copyright © 2020-2023  润新知