我是靠谱客的博主 友好发箍,最近开发中收集的这篇文章主要介绍算法练习 (8) 01背包问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目描述

给定一个有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背包问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部