码迷,mamicode.com
首页 > 编程语言 > 详细

POJ3624 0-1背包(dp+滚动数组)

时间:2018-08-24 19:26:49      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:int   put   describe   return   miss   desc   hat   integer   break   

Charm Bracelet
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 47440   Accepted: 20178

Description

Bessie has gone to the mall‘s jewelry store and spies a charm bracelet. Of course, she‘d like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a ‘desirability‘ factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).

Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di

Output

* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

Sample Input

4 6
1 4
2 6
3 12
2 7

Sample Output

23

 

如果用dp[n][m]:前n个物品不超过体积m的最大价值,状态转移方程为:

dp[i][j] = 0(i==0orj==0)//没有物品,背包体积再大的最大价值也是0;再多物品,背包体积为0都塞不下。

dp[i][j]=dp[i-1][j](j<d[i])//当前背包塞不下第i个物品,最大价值和第i-1个物品不大于体积j的最大价值是一样的。

dp[i][j]=max(dp[i-1][j],dp[i-1][j-d[i]]+w[i])//当前背包若能装下第i个物品,那么就在装第i个物品后的最大价值和不装第i个物品的最大价值中取最大值

但由于N和M的范围太大,开二维数组会爆内存,分析求解过程发现求解dp[i][j]时只与它上一行的正上方和上一行左边的某个值有关,也就是只用到了它上面那行,可以用一个滚动的一维数组求解,把新值放到上面的位置,但要注意顺序必须是从右到左,不然会覆盖掉有用的值。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int main()
 6 {
 7     int n, m;
 8     int d[13010], w[13010];
 9     int dp[13010];//因为求解该行时只与上一行有关,所以可以用滚动数组,dp[j]表示前i个物品在不超过体积j的最大价值
10     cin >> n >> m;
11     for (int i = 1; i <= n; ++i)
12     {
13         cin >> d[i] >> w[i];
14     }
15     memset(dp, 0, sizeof(dp));
16     for (int i = 1; i <= n; ++i)
17     {
18         for (int j = m; j >= 1; --j)//从右往左求解,把新求出的值保存在上面的位置,因为被覆盖的值只与它下面和下一行的右边有关
19         {
20             if (j >= d[i])
21                 dp[j] = max(dp[j], dp[j - d[i]] + w[i]);
22             else       //如果j-d[i]<0,说明当前背包的容量不够放第i个物品,那放前i个物品的最大价值与放前i-1个物品的最大价值是相等的,
23                 break;//又因为从右往左求值,左边的j只会更小,因此可跳过节省时间
24                         
25         }
26     }
27     cout << dp[m] << endl;
28     return 0;
29 }

 

POJ3624 0-1背包(dp+滚动数组)

标签:int   put   describe   return   miss   desc   hat   integer   break   

原文地址:https://www.cnblogs.com/knmxx/p/9531340.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!