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]);
}
}
小结
- 先遍历物品,再遍历背包
- 在01背包的基础上加上一个for循环,相当于展开多重背包
- 要注意i和j,谁是背包,谁是物品!
- 背包要从大到小减
139.单词拆分
思路:单词可以重复使用,是完全背包,我要怎么拆分字符串呢?能解决拆分这一点,直接用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()];
}
}
小结
- dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
- 递推公式: if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。
- 求排列,先背包,后物品