题目:70. 爬楼梯(进阶)
文章链接:代码随想录
题目链接:卡码网题目链接
图释:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
while(cin >> n >>m){
// m表示至多爬m个台阶 [1,2,...m] n表示楼顶数
// dp[i]表示达到第i个台阶有dp[i]中方法(排列问题)
vector<int> dp(n + 1, 0);
dp[0] = 1; // 初始化
// 因为dp[i]是靠dp[i-j]累计上来的,dp[i]本身为0这样才不会影响结果
for (int j = 1; j <= n; j++) { // 遍历背包
for (int i = 1; i<=m; i++) { // 遍历物品,
// 爬楼梯的阶数从1开始, 阶梯数小于至多数
if(i<=j) // 把爬楼梯的阶数要小于楼顶数 可以防止输入顺序未排列情况
dp[j] += dp[j - i];
}
}
cout<< dp[n] << endl;
}
}
题目:322. 零钱兑换
文章链接:代码随想录
视频链接:LeetCode:322.零钱兑换
题目链接:力扣题目链接
图释:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
// dp[i]表示 凑成总金额为i,最少的硬币个数
vector<int> dp(amount+1, INT_MAX);
// 非零下标初始化,由于递推公式min,所以取最大值
// 递推公式 :dp[j] = min(dp[j], dp[j-coins[i]]+1) dp[金额-硬币]+1 方法加一
dp[0] = 0; //凑成金额0,有0个硬币
// 遍历顺序 因为取的是最小值,所以排列或者组合方式都可以
for(int i=0; i<coins.size(); i++){ // 先遍历物品为组合数
for(int j=coins[i]; j<=amount; j++){ // 再遍历背包, 从小到大,为完全背包问题
if(dp[j-coins[i]] != INT_MAX){ // 如果dp[j - coins[i]]是初始值则跳过,就是说上一个金额数也没凑满
dp[j] = min(dp[j], dp[j-coins[i]]+1);
}
}
}
if(dp[amount]==INT_MAX) return -1; // 如果不能凑满背包,则返回-1
return dp[amount];
}
};
题目:279.完全平方数
文章链接:代码随想录
视频链接:LeetCode:279.完全平方数
题目链接:力扣题目链接
图释:
class Solution {
public:
int numSquares(int n) {
// 首先先把完全平方数给组数来作为物品
vector<int> Square;
int Num=1;
while(Num<=n){
int sum = Num * Num;
if(sum>n) break;
Square.push_back(sum);
Num++;
}
// 定义dp[i]数组 和为i的完全平方数的最少数量dp[i]
vector<int> dp(n+1, INT_MAX);
dp[0]=0;
for(int i=0; i<Square.size(); i++){ // 遍历物品
for(int j=Square[i]; j<=n; j++){ // 再遍历背包
// if(dp[j-Square[i]] != INT_MAX){ // 有个平方数1,不会凑不满
dp[j] = min(dp[j], dp[j-Square[i]]+1);
// }
}
}
return dp[n];
}
};
// 简洁版
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++) { // 遍历背包
dp[j] = min(dp[j - i * i] + 1, dp[j]);
}
}
return dp[n];
}
};