day17动态规划4

494.目标和

int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0;
        //vector<int> dp(1501, 0);
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
        }
        if (abs(target) > sum) return 0; // 此时没有方案
        if ((target + sum) % 2 == 1) return 0; // 此时没有方案

        int bagSize = (target + sum) / 2;
        vector<int> dp(bagSize+1, 0);
        dp[0]=1;
        for (int i = 0; i <nums.size(); i++) { // 遍历物品
            for (int j = bagSize; j >= nums[i]; j--) { // 遍历背包容量// 每一个元素一定是不可重复放入,所以从大到小遍历
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[bagSize];
    }

474.一和零

int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m+1, vector<int>(n+1,0)); 默认初始化0
        for(string str:strs){// 遍历物品
            int x=0,y=0;
            for(char c:str){
                if(c=='0') x++;
                else y++;
            }
            for(int i=m;i>=x;i--){// 遍历背包容量且从后向前遍历!
                for(int j=n;j>=y;j--){
                    dp[i][j]=max(dp[i][j],dp[i-x][j-y]+1);
                }
            }
        }
        return dp[m][n];
    }

518.零钱兑换II

int change(int amount, vector<int>& coins) {
        vector<int> dp(amount+1, 0);
        dp[0]=1;
        for (int i = 0; i <coins.size(); i++) { // 遍历物品
            for (int j = coins[i]; j <= amount; j++) { // 遍历背包容量
                dp[j] += dp[j - coins[i]];
            }
        }
        return dp[amount];
    }

打印的代码

#include<iostream>
#include<vector>
using namespace std;
int change(int amount, vector<int>& coins) {
    vector<int> dp(amount + 1, 0);
    dp[0] = 1;
    for (int i = 0; i < coins.size(); i++) { // 遍历物品
        cout <<endl<< "i = " << i << ":  "<<endl;
        for (int j = coins[i]; j <= amount; j++) { // 遍历背包容量
            dp[j] += dp[j - coins[i]];
            cout << "j = " << j << ", dp[j] = " << dp[j] << endl;
        }
    }
    cout << "dp[]:" << endl;
    for (int i : dp) {
        cout << i << "  ";
    }
    return dp[amount];
}
int main() {
    vector<int> coins = { 1,2,5 };
    cout << endl<< change(5, coins) << endl;
    return 0;
}

在这里插入图片描述

假如for改变位置:(变成了排列),是不符合本题的意思的

#include<iostream>
#include<vector>
using namespace std;
int change(int amount, vector<int>& coins) {
    vector<int> dp(amount + 1, 0);
    dp[0] = 1;
    for (int j = 0; j <= amount; j++) { // 遍历背包容量
   
        cout << endl << "j = " << j << ":  " << endl;
        for (int i = 0; i < coins.size(); i++) { // 遍历物品
            if (j - coins[i] >= 0) {
                dp[j] += dp[j - coins[i]];
                cout << "**有更新**" << j - coins[i] <<"   ";
            }    
            cout << "i = " << i << ", dp[j] = " << dp[j] << endl;
        }
    }
    for (int i : dp) {
        cout << i << "  ";
    }
    return dp[amount];
}
int main() {
    vector<int> coins = { 1,2,5 };
    cout << endl << change(5, coins) << endl;
    return 0;
}

在这里插入图片描述

377. 组合总和 Ⅳ

若是爬楼梯 那道题,拓展成为 一步可以爬m个台阶,就是和本题一样的题目了。求的是排列数还是组合数?(排列数)。
遍历顺序可以颠倒吗?(不可以)
颠倒时 是什么场景(组合?上一题518.零钱兑换II),不颠倒又是什么场景?(本题377. 组合总和 Ⅳ 以及爬楼梯 一步可以爬m个台阶)

如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。

int combinationSum4(vector<int>& nums, int target) {
         vector<int> dp(target + 1, 0);
        dp[0] = 1;
        for (int j = 0;  j<= target; j++) { // 遍历背包
            for (int i = 0; i< nums.size(); i++) { // 遍历物品
                if (j - nums[i] >= 0 && dp[j] < INT_MAX - dp[j - nums[i]]) {
                //if (j - nums[i] >= 0 ) {
                    dp[j] += dp[j - nums[i]];
                }
            }
        }
        return dp[target];
    }

爬楼梯 那道题,拓展成为 一步可以爬m个台阶

int climbStairs(int n) {
        vector<int> dp(n + 1, 0);
        dp[0] = 1;
        for (int j = 1; j <= n; j++) { // 遍历背包  //共n层楼梯
            for (int i = 1; i <= m; i++) { // 遍历物品
                if (j - i >= 0) dp[j] += dp[j - i];
            }
        }
        return dp[n];
    }

322. 零钱兑换

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 - coins[i]]是初始值则跳过
                    dp[j]=min(dp[j-coins[i]]+1, dp[j]);
                }
            }
        }
        if(dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }
int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, INT_MAX);
        dp[0] = 0;
        
        for(int j=1;j<=amount;j++){// 遍历背包
            for(int i=0;i<coins.size();i++){// 遍历物品
                if(j-coins[i]>=0  &&  dp[j-coins[i]] != INT_MAX){// 如果dp[j - coins[i]]是初始值则跳过//两个条件不能位置调换,否则会溢出
                    dp[j]=min(dp[j-coins[i]]+1, dp[j]);
                }
            }
        }
        if(dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }

279.完全平方数

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];
    }
int numSquares(int n) {
        vector<int> dp(n + 1, INT_MAX);
        dp[0] = 0;
        
        for(int j=0;j<=n;j++){// 遍历背包
            for(int i=1;i*i<=j;i++){// 遍历物品
                    dp[j]=min(dp[j-i*i]+1, dp[j]);       
            }
        }
        return dp[n];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值