题目描述
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
样例
输入描述:
复制代码
1
2
3输入为两行: 第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000) 第二行为n个正整数A[i](32位整数),以空格隔开。
输出描述:
复制代码
1输出所求的方案数
示例1
输
复制代码
15 15 5 5 10 2 3
输出
复制代码
14
思路分析
01背包的状态转移方程 f[i,j] = max{f[i-1,j-wi] + p[i](j>=wi), f[i-1,j]}
f[i,j]表示在前i件物品中,选择若干件放在承重为j的背包中,可以取得的最大价值,pi表示第i件物品的价值,wi表示第i件物品的重量
此题中,无物体重量w的概念,而sum可以看做物品价值
列出表格如下
做法
1.由于每个数总能把0填上,且0不可填上初0外其余数,所以数组第一行全填0,第 一列全填1;
2.从第二行第二列开始遍历数组。如果列所在数字减去该行数小于0(即j < value[i]),那么该格子继承本列上一行的数字。例如图中(2,10)对应格子。由于让10得到2,那必须由-8+5得到,但是该题无法得到比0小的数,因此由10之前的数得到2的最多可能与他之前的数(即5)是一样的;
3.如果列所在数字减去该行数大于等于0(
j >= value[i]),该格子内容为该列上一行数字与上一行差值所在格子数量和。什么意思呢?例如(10,3),若想要用3之前的数列得到10,除了 它上一行(即2)本身就能得到2个10外,只要之前的数字是7,7+3依然可以得到10。因此去看上一行中列数为7的格子数值,为2,即它上一个数有2中组合得到7,7+3=10。那该行数值即为2+2=4。
代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public static void main(String[] args) { Scanner s = new Scanner(System.in); int n = s.nextInt(); int sum = s.nextInt(); int value[] = new int[n]; long dp[] = new long[sum+1]; dp[0] = 1; for (int i = 0; i < n; i++) { value[i] = s.nextInt(); for (int j = sum; j >= 0; j--) { if (j >= value[i]) { dp[j] = dp[j] + dp[j - value[i]]; } } } System.out.println(dp[sum]); }
结果
最后
以上就是友好发箍最近收集整理的关于算法练习 (8) 01背包问题的全部内容,更多相关算法练习内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复