代码随想录Day51 | 139.单词拆分 多重背包

本文介绍了如何使用动态规划解决LeetCode中的139.单词拆分问题,以及将多重背包问题转化为01背包问题的方法,通过示例展示了如何计算给定单词列表下,如何组合单词填满背包。
摘要由CSDN通过智能技术生成

代码随想录Day51 | 139.单词拆分 多重背包

139.单词拆分

文档讲解:代码随想录
视频讲解: 你的背包如何装满?| LeetCode:139.单词拆分
状态

  1. dp数组
    dp[j] 表示一个长度为j的单词可以由数组中的单词组成即为true,否则就是false
  2. 递推公式
    当一个i>j且[j,i]这个字符串存在于数组中,且dp[j]为true那么结果就是true
  3. 初始化
    dp[0] = true 其他初始化为false
  4. 遍历顺序
    对于这道题我们应当使用求排列。因为两个单词的顺序决定了是否合理
    所以先遍历背包再遍历物品
  5. 打印dp
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        int ssize = s.size();
        //利用hash表来方便查找
        unordered_set<string> wordSet(wordDict.begin(),wordDict.end());
        vector<int> dp(ssize+1,0);
        dp[0] = 1;
        //背包:长度为j的字符串
        for(int j = 1;j<=ssize;j++)
        {
            //物品:数组列表的单词
            //用i来控制新增的长度
            for(int i = 0;i<j;i++)
            {
                //考虑新增字符串
                string word = s.substr(i,j-i);
                if(wordSet.find(word) != wordSet.end() && dp[i] == 1)
                {
                    dp[j] = 1;
                }
            }
        }
        if(dp[ssize] == 1) return true;
        return false;
    }
};

多重背包

文档讲解:代码随想录
视频讲解:
状态

本质上就是01背包,只不过对于每种物品的个数大于等于1,但不是无限的。
具体解决方法就是利用01背包,然后对每个物品在判断是否选择的时候,改为选取多少个。

  1. dp数组
    dp[j] 表示容量为j的背包的最大价值
  2. 递推公式
    对于一个物品可以选取k个,那么如果超过了容量,就是dp[j],如果没有超过容量就选择dp[j-k*weight[i]]+k*price[i];
dp[j] = max(dp[j],dp[j-k*weight[i]]+k*price[i];
  1. 初始化
    dp[i] = 0
  2. 遍历顺序
    01背包,所以为了避免重复选择背包需要从后向前遍历,在对于每个物品的是否选择是还需要增加一个循环判断,选取k个物品是否合适
  3. 打印dp
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int C,N;
    cin >> C >> N;
    
    vector<int> weight(N,0);
    vector<int> price(N,0);
    vector<int> nums(N,0);
    for(int i = 0;i<N;i++)
    {
        cin >> weight[i];
    }
    for(int i = 0;i<N;i++)
    {
        cin >> price[i];
    }
    for(int i = 0;i<N;i++)
    {
        cin >> nums[i];
    }
    
    vector<int> dp(C+1,0);
    //转换为01背包
    for(int i = 0;i<N;i++)
    {
        //遍历背包
        for(int j = C;j>=weight[i];j--)
        {
            //对每个物品选择数量
            for(int k = 1;k<=nums[i]&&j-k*weight[i]>=0;k++)
            {
                    dp[j] = max(dp[j],dp[j-k*weight[i]]+k*price[i]);
            }
        }
    }
    cout << dp[C];
    return 0;
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值