[DP] 0/1 Knapsack Problem

本文详细解析0/1背包问题的动态规划解决方案,通过手写示例介绍如何初始化二维数组,给出递推公式,并逐步求解以获得最大价值组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题定义:

有n个item.每个item有weight和value两个值。有个容器,最多只能放K的weight. 求,如何能让容器中的value总和最大。

0/1 Knapsack 的0/1表示一个item要么放进去要么没有放进去,不能只放一部分进去。

思路:

经典的动态规划问题。

下面我用直接手写例子(本来打算用PPT做的。。。后来发现太麻烦了。。如果大家有更好的方法,可以留言给我。)

第一步:初始化一个二维数组。大小为n*m. n是item的个数,m是capacity大小+1. 例子如下:

 

第二步:给出公式。这里有两种情况。

         - 如果j<wt[i]. 就是当第i个item的weight比当前的j大了,该Item怎么也放不进去了。那就只能不放了。所以DP[i][j] = DP[i-1][j] . 意思就是和没放item i的情况一样。

         - 如果j>=wt[i]. 那就是item i能够放进去。但是注意,只是能够放进去。到底放不放还要看item i加进去后好不好。所以就又要有两种子情况。

              * 把item i放进去。 DP[i][j] = val[i] + DP[i][j-wt[i]]. //val[i]是item i的value. wt[i]是item i的weight. 

              *不把item i 放进去。 DP[i][j] = DP[i-1][j]

            上面两种子情况要一起考虑,所以要取他们的最大值。也就是DP[i][j] = max {val[i] + DP[i][j-wt[i]], DP[i-1][j]}. 也就是到底放不放item i就要看放了它后有没有好处[真是残忍啊!]

 

第三步: 按照公式,可以求出DP[n-1][m-1]的值。就是最终的最大值。

            但是,我们还想知道到底是放了哪几个item进去才达到最大值了[真是事多。。]

           所以,我们又要在那个DP二维表中从右下角往左上角找。具体方法是:

              - 先把DP[i][j]和DP[i-1][j]比较,看看是不是一样。如果一样,就说明item i没有被用到。那就说明item i不在结果中。

              - 如果不一样。就说明item i被用到了。然后跳到DP[i-1][j-wt[i]]的位置继续看。

例子在下面:

 

PS:字迹潦草。希望能看懂。。。。

 

转载于:https://www.cnblogs.com/cblin/p/6557649.html

The 0-1 Knapsack Problem is a classic optimization problem in computer science and mathematics. The problem is as follows: Given a set of items, each with a weight and a value, determine the items to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. The 0-1 indicates that each item can only be included once or not at all. This problem can be solved using dynamic programming. We can create a two-dimensional array where the rows represent the items and the columns represent the weight limit. For each item and weight limit, we can calculate the maximum value that can be obtained by either including the item or excluding it. We can then fill in the array row by row until we reach the final row, which represents the optimal solution. Here is an example implementation of the 0-1 Knapsack Problem in Java: ``` public class Knapsack { public static int knapsack(int[] values, int[] weights, int limit) { int[][] dp = new int[values.length + 1][limit + 1]; for (int i = 1; i <= values.length; i++) { for (int j = 1; j <= limit; j++) { if (weights[i-1] > j) { dp[i][j] = dp[i-1][j]; } else { dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weights[i-1]] + values[i-1]); } } } return dp[values.length][limit]; } public static void main(String[] args) { int[] values = {60, 100, 120}; int[] weights = {10, 20, 30}; int limit = 50; int result = knapsack(values, weights, limit); System.out.println("Maximum value: " + result); } } ``` In this example, we have three items with values of 60, 100, and 120 and weights of 10, 20, and 30, respectively. We want to find the maximum value we can obtain with a weight limit of 50. The result is 220, which indicates that we should select items 2 and 3 to maximize the value while staying under the weight limit.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值