动态规划专题(三个例题:简单、中等、中等)

例题一:连续数列(力扣面试题16.17 简单)

题目链接:力扣icon-default.png?t=M0H8https://leetcode-cn.com/problems/contiguous-sequence-lcci/

题目:给定一个整数数组,找出总和最大的连续数列,并返回总和。

示例

输入: [ -2, 1, -3, 4, -1, 2, 1, -5, 4]

输出:6

解释:连续子数组[ 4, -1, 2, 1]的和最大, 为6

题目分析:用一个数来动态存放连续的数的和, 然后找出最大值。

代码

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        int ans = 0, res = nums[0];//ans用来存放连续的值的和,res来存放最大值
        for(int i = 0; i < n; i ++)
        {
            ans = max(ans + nums[i], nums[i]); //用来存放连续的值的和
            res = max(res, ans);
        }
        return res;
    }
};

例题二:最小路径和(力扣64 中等)

题目链接:力扣icon-default.png?t=M0H8https://leetcode-cn.com/problems/minimum-path-sum/

题目:给定一个包含非负数的m X n网格grid,请找出一条从左上角到右下角的路径,使得路径的数字总和为最小。(说明:每次只能向下或者向右移动一步)

示例 1:

输入: grid = [ [ 1, 2, 1], [ 1, 5, 1], [ 4, 2, 1]]

输出: 7

解释: 因为路径 1->3->1->1->1的总和最小

示例 2

输入: grid = [ [ 1, 2, 3], [ 4, 5, 6]]

输出: 12

题目分析:用一个二维数组来存放到每个点的最小路径和,第一行和第一列的最小路径就是该行或者该列的开头到该点的和, 到(i, j)点的最小路径和为该点的路径+到(i - 1, j) 和到 (i, j - 1)中的最小值。

代码

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector<vector<int>> ans(n, vector<int>(m)); //用来记录到(i, j)的路径
        ans[0][0] = grid[0][0];
        for(int i = 1; i < n; i ++) ans[i][0] = ans[i - 1][0] + grid[i][0];
        for(int i = 1; i < m; i ++) ans[0][i] = ans[0][i - 1] + grid[0][i];
        for(int i = 1; i < n; i ++)
        {
            for(int j = 1; j < m; j ++)
                ans[i][j] = min(ans[i][j - 1], ans[i - 1][j]) + grid[i][j];
        }
        return ans[n - 1][m - 1];
    }
};

例题 三: 粉刷房子(剑指Offer II  91  中等)

题目链接:力扣icon-default.png?t=M0H8https://leetcode-cn.com/problems/JEj789/

题目:假如有一排房子,共有n个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同的颜色的花费是以一个n X 3的正整数矩阵costs来表示。例如,costs[0][0]表示第0号房子粉刷成红色的成本花费;costs[1][0]表示第1号房子粉刷成绿色的花费,以此类推。请计算出粉刷完所有房子最少的花费成本。

示例 1

输入: costs = [ [ 17, 2, 17], [ 16, 16, 5], [ 14, 3, 19]]

输出: 10

解释: 将0号房子粉刷成蓝色, 1号房子粉刷成绿色, 2号房子粉刷成蓝色。最少花费:2 + 5 + 3 = 10.

  

 示例 2

输入: costs = [ [ 7, 6, 2]]

输出: 2

 提示

  • costs.length == n
  • costs[i].length == 3
  • 1 <= n <= 100
  • 1 <= costs[i][j] <= 20

题目分析:用一个二维数组来存放第i个房子粉刷成第j号颜色的最少花费并且每个房子粉刷的颜色不同(dp[i][j]) = 第i个粉刷为第j号颜色的花费(costs[i][j]) + 第i - 1个房子粉刷成另外两个其中一个的颜色所需的最小花费(min(dp[i - 1][], dp[i - 1][])), 最后找出dp[n - 1]中的最小值即可。

代码

class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
        int n = costs.size();
        vector<vector<int>> dp(n, vector<int>(3)); //dp[i][j]用来记录第i号房子刷成j(红,蓝,绿)
        for(int i = 0; i < 3; i ++)
            dp[0][i] = costs[0][i];
        for(int i = 1; i < n; i ++)
        {
            dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0];
            dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1];
            dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2];
        }
        return min(dp[n - 1][0], min(dp[n - 1][2], dp[n - 1][1]));
    }
};

总结:

动态规划的核心是找到前后的联系(数学关系)和定义一些初始化的值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值