代码随想录Day49

56.携带矿石资源(卡码网)

题目:56. 携带矿石资源(第八期模拟笔试) (kamacoder.com)

思路:多重背包可以转换为01背包,本质上就是同一种物品有多个,展开之后就是01背包

答案
import java.util.Scanner;
class Main{
    public static void main(String [] args) {
        Scanner sc = new Scanner(System.in);

        /**
         * bagWeight:背包容量
         * n:物品种类
         */
        int bagWeight, n;
        
        //获取用户输入数据,中间用空格隔开,回车键换行
        bagWeight = sc.nextInt();
        n = sc.nextInt();
        int[] weight = new int[n];
        int[] value = new int[n];
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) weight[i] = sc.nextInt();
        for (int i = 0; i < n; i++) value[i] = sc.nextInt();
        for (int i = 0; i < n; i++) nums[i] = sc.nextInt();

        int[] dp = new int[bagWeight + 1];

        //先遍历物品再遍历背包,作为01背包处理
        for (int i = 0; i < n; i++) {
            for (int j = bagWeight; j >= weight[i]; j--) {
                //遍历每种物品的个数
                for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {
                    dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
                }
            }
        }
        System.out.println(dp[bagWeight]);
    }
}
小结
  1. 先遍历物品,再遍历背包
  2. 在01背包的基础上加上一个for循环,相当于展开多重背包
  3. 要注意i和j,谁是背包,谁是物品!
  4. 背包要从大到小减

139.单词拆分

题目:139. 单词拆分 - 力扣(LeetCode)

思路:单词可以重复使用,是完全背包,我要怎么拆分字符串呢?能解决拆分这一点,直接用map就能解决这题,我想,可以把字符串的“a-z”给统计出来,看一下能不能通过组合字典的单词,跟这个数组重合,背包大小就是字符串的长度,物品就是单词,单词的长度是物品重量,找到所有跟符合容量的物品组合,再看一下字符串是否匹配?

尝试(想不出来)
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        int bagweight = s.size();
        // 得到物品重量数组
        int[] weight = new int[wordDict.size()];
        int count = 0;
        for(String s : wordDict){
            weight[count] = s.size();
            count++;
        }
        // 得到所有排列
        int[] dp = new int[bagweight+1];
        dp[0] = 1;
        for(int i=0; i<weight.length; i++){
            for(int j =0; j <= bagweight; j++){
                dp[j] = Math
            }
        }
        // 判断排列中是否有符合的字符串,有则返回true

        // 默认返回false
    }
}
答案
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> set = new HashSet<>(wordDict);
        boolean[] valid = new boolean[s.length() + 1];
        valid[0] = true;

        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i && !valid[i]; j++) {
                if (set.contains(s.substring(j, i)) && valid[j]) {
                    valid[i] = true;
                }
            }
        }

        return valid[s.length()];
    }
}
小结
  1. dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词
  2. 递推公式: if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。
  3. 求排列,先背包,后物品
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值