copyright zvvq
0-1 袋子问题
主题描述
Ming 是一位科学家,他需要参加一个重要的国际科学会议来展示他的最新研究成果。他需要带一些研究资料,但他的行李箱空间有限。这些研究资料包括实验设备、文献、实验样本等,各自占据不同的空间,具有不同的价值。
内容来自samhan666
Ming的行李空间为N。问Ming应该如何选择携带最有价值的研究资料。每个研究材料只能选择一次,并且只有选择或不选择两种选择,并且不能进行裁剪。 内容来自zvvq
输入描述
zvvq好,好zvvq
第一行包含两个正整数,第一个整数M代表研究材料的类型,第二个正整数N代表Ming的行李空间。第二行包含 M 个正整数,代表每种研究材料占用的空间。 zvvq.cn
第三行包含M个正整数,代表每个研究材料的价值。
内容来自zvvq,别采集哟
输出描述 zvvq.cn
输出一个整数,代表Ming可以携带的研究材料的最大值。输入示例
内容来自samhan
6 1 内容来自samhan
2 2 3 1 5 2 zvvq
2 3 1 5 4 3输出示例
提示
zvvq.cn
小明可以携带6个研究材料,但行李空间只有1个,而占用1个空间的研究材料价值5个,所以最终答案是输出5。数据范围: 内容来自samhan666
1 1 研究材料占用空间和研究材料价值均小于等于1000。 内容来自samhan
1 本文来自zvvq
2 内容来自zvvq,别采集哟
3
4
5
zvvq
6
本文来自zvvq
7 内容来自samhan
8 内容来自zvvq
9
10 内容来自samhan
11
12
13
14 本文来自zvvq
15
16
17
18
19 内容来自zvvq,别采集哟
20 内容来自samhan666
21
22
23 内容来自samhan666
24
zvvq.cn
25
zvvq.cn
26
copyright zvvq
27 copyright zvvq
28
内容来自zvvq
29
30
31 zvvq
32 本文来自zvvq
33 本文来自zvvq
34
35
公开课主{ 内容来自samhan666
公共静态无效主(字符串[]参数){
copyright zvvq
/ 代码 /
copyright zvvq
扫描仪 s = new Scanner(System.in);
copyright zvvq
int M = s.nextInt();
int N = s.nextInt();
内容来自zvvq
// 清除缓冲区符号 /n
s.nextLine();
字符串 w = s.nextLine();
字符串 v = s.nextLine();
int[] 权重 = Arrays.stream(w.split(" "))
zvvq好,好zvvq
.mapToInt(整数::valueOf)
内容来自zvvq,别采集哟
.toArray(); 本文来自zvvq
int[] value = Arrays.stream(v.split(" ")) zvvq.cn
.mapToInt(整数::valueOf) 内容来自samhan
.toArray(); zvvq好,好zvvq
int[][] dp = 新 int[M][N+1];
内容来自zvvq
for(int i=权重[0]; i j){ 内容来自samhan
dp[i][j] = dp[i-1][j]; zvvq好,好zvvq
}别的{ zvvq好,好zvvq
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - 权重[i]] + 值[i]);
内容来自zvvq,别采集哟
} 内容来自samhan
} 内容来自samhan
} zvvq好,好zvvq
System.out.println(dp[M-1][N]); 内容来自samhan666
}
内容来自zvvq,别采集哟
} 内容来自zvvq
1,dp数组意味着我们可以获得item i和目标bag size j的最大值。行表示物品,列表示包的尺寸。
2,对于init,我们初始化第一行和第一列(但实际上我们默认初始化列为0,这意味着) zvvq
3,回归关系为:对于每一项:
a、如果物品的重量大于包的尺寸,则无法选择该物品,当前尺寸为之前选择的物品集合的尺寸。 内容来自zvvq
b、如果物品的重量可以,我们必须比较之前选择的物品的集合的大小减去当前物品的大小(如果我们不这样做,则总大小将是大小 + 大小当前项目的,它将破坏我们的 dp 数组的逻辑)。这里,是双循环的顺序,因为我们可以用一个二维数组来记录所有结果,从上一行开始查找当前行。
另外,我们可以使用一维数组来实现。
1 zvvq好,好zvvq
2
3
4 copyright zvvq
5 内容来自samhan
6
内容来自samhan
for(int i=1; i<m i for j="1;" if> j){
zvvq
dp[i][j] = dp[i-1][j]; zvvq.cn
}别的{ zvvq
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - 权重[i]] + 值[i]);
}
</m>
zvvq.cn
改成
1 zvvq好,好zvvq
int[] dp = new int[target+1];
zvvq好,好zvvq
1
2
zvvq.cn
3 zvvq
4
内容来自zvvq
5
6 zvvq
7
内容来自samhan
8 内容来自zvvq,别采集哟
for(int i=1; i<nums.length i for j="目标;">=1; j--){ 内容来自samhan666
if(nums[i] > j){
zvvq
继续; zvvq好,好zvvq
}
dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i]);
} zvvq.cn
}
内容来自zvvq
</nums.length>
416. 划分子集和相等
给定一个整数数组 nums,如果可以将数组划分为两个子集,使得两个子集中的元素之和相等,则返回 true,否则返回 false。
zvvq好,好zvvq
示例1:
输入:nums = [1,5,11,5] 内容来自zvvq
输出:true 内容来自zvvq
说明:数组可以分为 [1, 5, 5] 和 [11]。
zvvq.cn
示例2:输入:nums = [1,2,3,5] 内容来自zvvq
输出:假 copyright zvvq
说明:数组不能划分为等和子集。限制: 内容来自zvvq,别采集哟
1 1 原始页面 本文来自zvvq
1 内容来自samhan666
2
3 copyright zvvq
4 内容来自samhan
5 内容来自samhan666
6 zvvq好,好zvvq
7
8
9 内容来自zvvq,别采集哟
10
内容来自zvvq,别采集哟
11
内容来自samhan
12 本文来自zvvq
13 本文来自zvvq
14
15 zvvq.cn
16
17
copyright zvvq
18 内容来自zvvq
19 内容来自samhan
public boolean canPartition(int[] nums) { copyright zvvq
int sum = Arrays.stream(nums).sum();
如果(总和%2==1){ 内容来自samhan
返回假; 内容来自zvvq
}
int 目标=总和>>1;
copyright zvvq
int[][] dp = new int[nums.length][目标+1];
zvvq
for(int i=nums[0]; i j){ zvvq
dp[i][j] = dp[i-1][j];
内容来自samhan
}别的{
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-nums[i]] + nums[i]);
} copyright zvvq
}
zvvq好,好zvvq
}
zvvq.cn
返回 dp[nums.length-1][目标] == 目标; 内容来自zvvq,别采集哟
} zvvq
以上就是LeetCode Day动态编程第31部分的详细内容,更多请关注其它相关文章! 内容来自samhan666