一、爬楼梯(进阶)
一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢?
思路
1.dp[i]:爬到第i个台阶有dp[i]种方法
2.递推公式:dp[i] += dp[i - j]
3.初始化:dp[0] = 1 ,其他非零下标的dp数组初始化为0
4.遍历顺序:先遍历背包再遍历物品(求排列)
实现代码
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n + 1, 0);
dp[0] = 1;
for (int i = 1; i <= n; i++) {
// 遍历背包
for (int j = 1; j <= m; j++) {
// 遍历物品
if (i - j >= 0) dp[i] += dp[i - j];
}
}
return dp[n];
}
};
二、零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
思路
1.dp[j]:装满容量为j的背包最少用dp[j]件物品
2.递推公式: dp[j] = min(dp[j - coins[i]] +1,dp[j])
3.初始化: dp[0] = 0 非零下标的dp的数组初始化为INT_MAX
4.遍历顺序:先遍历物品再遍历背包(和元素顺序无关所以可颠倒)
实现代码
//先遍历物品再遍历背包
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++) {
if(dp[j - coins[i]] != INT_MAX) {
dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
}
}
}
if(dp[amount] == INT_MAX) return -1;
return dp[amount];
}
};
//先遍历背包再遍历物品
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1, INT_MAX);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.size(); j++) {
if (i - coins[j] >= 0 && dp[i - coins[j]] != INT_MAX ) {
dp[i] = min(dp[i - coins[j]] + 1, dp[i]);
}
}
}
if (dp[amount] == INT_MAX) return -1;
return dp[amount];
}
};
三、完全平方数
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
思路
1.dp[j]:装满容量为j的背包最少需要dp[j]个元素
2.递推公式:dp[j] = min(dp[j - i*i]+1,dp[j])
3.初始化:dp[0] = 0 非零下标的dp的数组初始化为INT_MAX
4.遍历顺序:先遍历物品再遍历背包(和元素顺序无关所以可颠倒)
实现代码
//先遍历物品再遍历背包
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];
}
};
//先遍历背包再遍历物品
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n + 1, INT_MAX);
dp[0] = 0;
for(int i = 0; i <= n; i++) {
for(int j = 1; j * j <= i; j++) {
dp[i] = min(dp[i - j * j] + 1, dp[i]);
}
}
return dp[n];
}
};