动态规划

爬楼梯问题

1. 题目

爬楼梯每次可以爬1阶或两阶,问到n阶有多少种方法

2. 思路

状态:dp[i]表示到第i阶的走法
状态转移方程:dp[i] = dp[i-1] + dp[i-2]
边界状态值:dp[1] = 1, dp[2] = 2

3. 代码

int climbStairs(int n)
{
    std::vector dp(n+3, 0);
    dp[1] = 1;
    dp[2] = 2;
    for (int i = 3; i <= n; i++) {
        dp[i] = dp[i-1] + dp[i-2];
    }
    return dp[n];
}

打家劫舍

1. 题目

一组相邻的n个房屋,每个房屋有不等数量的财宝,盗贼想要盗取财物,但是从相邻的房屋盗取会出发警报,问在不触发警报的情况下,最多可以盗取多少财宝?

2. 思路

  • 状态:dp[i]表示前i个房间能获得的最大财宝
  • 状态转移方程:
    如果选择第i个房间,dp[i] = dp[i-2] + dp[i];不选择第i个房间,dp[i] = dp[i-1];
    所以dp[i]的最优解为dp[i] = max(dp[i-2] + dp[i], dp[i-1])
  • 边界状态值:
    dp[0] = num[0],
    dp[1] = max(num[0], num[1])

3. 代码

int rot(std::vector &nums)
{
    if (nums.size() == 0) {
        return 0;
    }
    if (nums.size() == 1) {
        return nums[0];
    }
    std::vector dp(nums.size(), 0);
    dp[0] = nums[0];
    dp[1] = std::max(nums[0], nums[1]);
    for (int i = 2; i < nums.size(); i++) {
        dp[i] = std::max(dp[i-1], dp[i-2]+nums[i]);
    }
    return dp[nums.size() - 1 ];
}

最大子段和

1. 题目

给定一个数组,求这个数组的连续子数组中,最大的那一段的和

2. 思路

  • 状态:dp[i] 表示以第i个数字结尾的最大子段和
  • 状态转移方程
    若dp[i-1] > 0, dp[i] = dp[i-1] + num[i]
    若dp[i-1] < 0, dp[i] = num[i]
    所以:dp[i] = max(dp[i-1] + num[i], num[i])
  • 边界状态值:dp[0] = num[0]

3. 代码

int maxSubArray(std::vector &num)
{
    std::vector dp(num.size(), 0);
    dp[0] = num[0];
    int max_res = dp[0];

    for (int i = 1; i < num.size(); i++) {
        dp[i] = std::max(dp[i - 1] + num[i], num[i]);  // 状态转移方程
        if (max_res < dp[i]) {
            max_res = dp[i];
        }
    }
    return max_res;
}

你可能感兴趣的:(动态规划)