【Day45】代码随想录之动态规划part7—爬楼梯(进阶)、零钱兑换、完全平方数

今天又是补打卡的一天,开冲!!!

今日任务:

  • 70.爬楼梯(进阶)
  • 322.零钱兑换
  • 279.完全平方数

题目一:爬楼梯(进阶)

这道题之前做过一次,但是可以采用完全背包的问题来分析一遍。

卡玛网题目:【57.爬楼梯】

在这里插入图片描述
这个题目其实是更难了一点,因为前面的题目都是每次要不爬1阶楼梯,要不爬2阶楼梯,现在相当于是任选,而且还是可以重复利用的,因此此问题可以转化为排列方式的完全背包问题。
按照递归五部曲:
(1)定义dp数组及其含义:
dp[j]表示爬到j阶楼梯,有dp[j]种方法。
(2)确定递推公式:
因为这个是方法类的,所以递推公式通常为:dp[j] = dp[j-nums[i]],此题种的nums[i]对应的就是1、2、3、4这种,因此可以转换为dp[j] = dp[j-i];
(3)dp数组初始化:
dp[0] = 1;如果初始化dp[0] = 0,那后面的全部都是0;
(4)确定遍历顺序:
因为这个是排列的完全背包问题;
完全背包问题相对于01背包问题,其实是第二层变成了从左到右遍历,然后因为又是排列的问题,所以是先背包后物品。
(5)打印dp数组:
一般用来判断和自己想的是否一致

易错点:在递推公式前面需要判断一下才能放,这个是完全背包排列问题中非常重要的东西


#include <iostream>
#include <vector>
using namespace std;

int main(){
    
    int m = 0, n = 0;
    while(cin >> n >> m){
        vector<int> dp(n+1);
        dp[0] = 1;
        for(int i = 1; i<=n; i++){
            for(int j = 0; j<=m; j++){
                if(i>=j) dp[i] += dp[i-j];
            }
        }
        cout << dp[n];
    }
    return 0;
}

题目二:零钱兑换

Leetcode题目:【322.零钱兑换】

在这里插入图片描述

从题目中大致可以看出来是完全背包类的题目,按照递归五部曲:
1、定义dp数组的含义:dp[j]表示装满j,最少的硬币数目为dp[j];
2、确定递推公式:
dp[j] = min(dp[j-coins[i]] + 1, dp[j]);
3、初始化:
dp[0] = 0;
因为取得都是最小,故为了不影响式子的值,所以需要初始化最大值;
4、遍历顺序:
按照完全背包的问题,可以是组合也可以是排列问题;
5、打印dp数组

此处需要注意在递推公式的判断条件,因为有可能dp[i]某些并不会初始化。


class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, INT_MAX);
        dp[0] = 0;
        for(int i = 0; i<coins.size(); i++){
            for(int j = coins[i]; j<=amount; j++){
                //dp[j] = min(dp[j], dp[j-coins[i]] + 1);
                if (dp[j - coins[i]] != INT_MAX){
                    dp[j] = min(dp[j], dp[j-coins[i]] + 1);
                }
            }
        }

        if (dp[amount] == INT_MAX) return -1;
        for(int i = 0; i<=amount; i++){
            cout << dp[i] << " ";
        }

        return dp[amount];
    }
};

题目三:279.完全平方数

Leetcode题目:【279.完全平方数】

在这里插入图片描述
这个题跟上面的题目基本一样,只不过此题需要我们自己去创造物品,物品就是i*i,因为完全平方数中存在1,所以不可能存在不能拼凑的情况。

按照递归五部曲:
(1)确定dp数组含义:dp[j]表示装满数量为j的背包,需要的最少完全平方数的个数;
(2)确定递推公式:
dp[j] = dp[j-nums[i]] + 1 变为dp[j] = dp[j-ii] + 1,因为是求最小,所以
dp[j] = min(dp[j], dp[j-i
i] + 1);
(3)初始化:dp[0] = 0,同时其他设置为最大值INT_MAX;
(4)确定遍历顺序:
因为此题是完全背包问题,所以都是正序,因为是组合问题,所以可以先物品再背包;
(5)打印dp数组;

class Solution {
public:
    int numSquares(int n) {
        // 题目就是自己去构造物品
        vector<int> dp(n+1, INT_MAX);
        dp[0] = 0;
        for(int i = 1; i*i <= n; i++){
            for(int j = i*i; j<=n; j++){
                if(dp[j-i*i] != INT_MAX){
                    dp[j] = min(dp[j], dp[j-i*i] + 1);
                }
            }
        }
        return dp[n];
    }
};
  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值