zoukankan      html  css  js  c++  java
  • POJ 3624 Charm Bracelet(简单DP,01背包)

    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
    题意:
      
      就是一道常见的01背包问题。(01背包就是物品可以取0件或者1件)
    题解:
      
      01背包的递推关系式:
        dp[i+1][j]表示从0到i这i+1个物品中选出总重量不超过j的物品时总价值的最大值。
        dp[0][j]=0
        dp[i+1][j]=dp[i][j]  (j<w[i])
        dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i])  (其他)
    然后根据这个关系式很容易写出代码。
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=5000;
    int v[maxn],w[maxn];
    int dp[maxn][13000];
    int main()
    {
        int n,m;
        while(cin>>n>>m)
        {
            for(int i=0;i<n;i++)
                cin>>w[i]>>v[i];
            for(int i=0;i<n;i++)
                for(int j=0;j<=m;j++)
                {
                    if(j<w[i])
                        dp[i+1][j]=dp[i][j];
                    else
                        dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);
                }
            cout<<dp[n][m]<<endl;
        }
        return 0;
    }

    然而题目要求内存很小,导致MLE了(二维数组太大,需要占用很多内存)。然后发现计算dp第i行时只用到dp第i-1行的数据。因此,可以用压缩成一维数组进行计算。但要注意,应从后住前推算。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=3500;
    int v[maxn],w[maxn];
    int dp[13000];
    int main()
    {
        int n,m;
        while(cin>>n>>m)
        {
            memset(dp,0,sizeof(0));
            for(int i=0;i<n;i++)
                cin>>w[i]>>v[i];
            for(int i=0;i<n;i++)
                for(int j=m;j>=w[i];j--)
                {
                    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
                }
            cout<<dp[m]<<endl;
        }
        return 0;
    }


  • 相关阅读:
    C:表达式、语句、声明
    SAIO Swift All In One Diablo版 安装指南 Alpha
    Python自然语言处理学习笔记(60):7.1 信息抽取
    Python自然语言处理学习笔记(59):练习
    Python自然语言处理学习笔记(62):7.3 开发和评价分块器
    doctest模块的使用说明
    Python自然语言处理学习笔记(61):7.2 分块
    Python自然语言处理学习笔记(57):小结
    使用cURL操作Openstack对象存储的ReST API
    认证系统
  • 原文地址:https://www.cnblogs.com/orion7/p/7485633.html
Copyright © 2011-2022 走看看