概述
题目描述
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
样例
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数A[i](32位整数),以空格隔开。
输出描述:
输出所求的方案数
示例1
输
5 15 5 5 10 2 3
输出
4
思路分析
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。
代码
public 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背包问题的全部内容,希望文章能够帮你解决算法练习 (8) 01背包问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复