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


    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 }
  • 相关阅读:
    vscode已有64位版本。
    git代码回滚的两种选择
    代码维护的问题
    草珊瑚理解IFC(inline formatting context)
    nodejs的dependency.md
    如何实现在H5里调起高德地图APP?(下)
    如何实现在H5里调起高德地图APP?(上)
    酸奶妈妈再次回归~
    【从零开始学】如何在安卓平台上实现定位?
    如何将四大名著和地图相结合?
  • 原文地址:https://www.cnblogs.com/knmxx/p/9531340.html
Copyright © 2020-2023  润新知