思路:这就是一道完全背包的排列问题,首先完全背包的问题,首先确定从前往后遍历,第二个排列问题,应该先遍历背包容量,再遍历物品,因为这样就可以保证出现
{1,5}
和{5,1}
的情况包含进去!
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
vector<int> dp(n+1,0);
dp[0]=1;
for(int i=1;i<=n;i++)//楼梯
{
for(int j=1;j<=m;j++)//可选择的一次爬多少楼梯
{
if(j>i)
{
dp[i]=dp[i];
}
else
{
dp[i]+=dp[i-j];
}
}
}
cout<<dp[n];
return 0;
}
思路:这道题的关键点在于选择合适的初始值!怎么样去判断是否找到了合适的金额!
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int MAX=amount+1;
vector<int> dp(amount+1,MAX);
dp[0]=0;
for(int i=1;i<=coins.size();i++)//先遍历物品
{
for(int j=1;j<=amount;j++)//再遍历硬币
{
if(coins[i-1]>j)
{
dp[j]=dp[j];
}
else
{
dp[j]=min(dp[j],dp[j-coins[i-1]]+1);
}
}
}
if(dp[amount]==MAX) return -1;
return dp[amount];
}
};
思路:一定要把背包和物品分清楚,背包容量就是我们要达到的值,每次取的数就是完全平方数的根号,最开始我陷入怎么去判断这个值是否是完全平方数的问题,我们从
j=1
开始,j*j
就是这个完全平方数,由j*j
得到的数肯定就是完全平方数!
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n + 1, INT_MAX);
dp[0] = 0;
for (int i = 1; i <= n; i++) { // 遍历背包
for (int j = 1; j * j <= i; j++) { // 遍历物品
dp[i] = min(dp[i - j * j] + 1, dp[i]);
}
}
return dp[n];
}
};
class Solution {
public:
int numSquares(int n) {
int max=n+1;
vector<int> dp(n+1,max);
dp[0]=0;
for(int i=1;i<=n;++i)
{
for(int j=i*i;j<=n;++j)
{
dp[j]=min(dp[j],dp[j-i*i]+1);
}
}
return dp[n];
}
};