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

2021-07-17 16:05

阅读:477

标签: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

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 2 #include 3 #include
 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 i)
12     {
13         cin >> d[i] >> w[i];
14     }
15     memset(dp, 0, sizeof(dp));
16     for (int i = 1; i 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]
23                 break;//又因为从右往左求值,左边的j只会更小,因此可跳过节省时间
24                         
25         }
26     }
27     cout  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


评论


亲,登录后才可以留言!