看不懂
valid数组为什么长度是s.length()+1
完全背包的排列问题。
字符串是背包,字典单词是物品,看字典单词是否可以填充完背包。
先遍历背包再遍历物品
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()];
}
}
有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。
可以等代成01背包问题。将重复的物品看成单独的物品。
递推公式:
最大价值:dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]);
最大容量:dp[j] = Math.max(dp[j], dp[j-weight[i]] + weight[i]);
方法数:dp[j] += dp[j-weight[i]];
最大子集个数:dp[j] = Math.max(dp[j], dp[j-weight[i]] + 1);
最小子集个数:dp[j] = Math.min(dp[j], dp[j-weight[i]] + 1);?
初始值:
最大价值最大容量最大子集个数:不用特意初始化
方法数:dp[0] = 1;
最小子集个数:dp[j] = Integer.MAX_VALUE;dp[0] = 0;
遍历顺序:
01背包
二维数组:先背包后背包都可以
一维数组:先物品再背包倒序(防止重复物品)
完全背包(背包正序)
组合:先物品再背包(不讲究排序)
排列:先背包再物品(排序)
多重背包
转化为01背包。
?for(int k = 1; k <= num[i] && (j - k * weight[i]) >= 0; k++) {//考虑重复的物品
? ? ? ? ? ? ? ? ? ? dp[j] = Math.max(dp[j], dp[j-k*weight[i]] + price[i] * k);
? ? ? ? ? ? ? ? }