1、LeetCode70爬楼梯
题目链接:70、爬楼梯
之前动态规划时做过一次:代码随想录70、爬楼梯 动态规划
本题爬1个、爬两个台阶中的1、2相当于物品,n相当于背包容量。
本题元素可以重复选取,属于完全背包问题,
而且不同的元素顺序算作不同方案,因此要先遍历背包。
1、dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法。
2、递推公式:dp[j] += dp[j - i]。
3、初始化:dp[0] = 1。
4、遍历顺序:先遍历背包,再遍历物品,正向遍历。
5、举例推导。
class Solution {
public:
int climbStairs(int n) {
vector dp(n+1, 0);
dp[0] = 1;
for (int j = 0; j <= n; j++)
{
for (int i = 1; i <= 2; i++)
{
if (j >= i)
{
dp[j] += dp[j - i];
}
}
}
return dp[n];
}
};
如果将代码中的2换成m,就是一次可以爬1-m个台阶。
2、LeetCode322零钱兑换
题目链接:322、零钱兑换
本题求的是最少硬币个数。
1、dp[j]:凑足总额为j所需钱币的最少个数为dp[j];
2、递推公式:
凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1。
dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
3、初始化:
凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;
每次都取最小值,所以dp[j]必须初始化为一个最大的数。
4、遍历顺序:本题求的是硬币个数,与顺序无关,先遍历物品还是背包都可以。
5、举例推导。
class Solution {
public:
int coinChange(vector& coins, int amount) {
vector 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], dp[j - coins[i]] + 1);
}
}
for (vector::iterator it = dp.begin(); it != dp.end(); it++)
{
cout << *it << "\t";
}
cout << endl;
}
if (dp[amount] == INT_MAX) return -1;
return dp[amount];
}
};
3、LeetCode279完全平方数
题目链接:279、完全平方数
1、dp[j]:和为j的完全平方数的最少数量为dp[j];
2、递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);
3、初始化:dp[0] = 0; 其余为INT_MAX;
4、遍历顺序:先遍历物品还是背包都可以,完全背包,从前向后遍历。
5、举例推导。
class Solution {
public:
int numSquares(int n) {
vector dp(n+1, INT_MAX);
dp[0] = 0;
for (int i = 0; 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];
}
};