zoukankan      html  css  js  c++  java
  • HDU 5410 CRB and His Birthday(完全背包变形)

    CRB and His Birthday

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 430    Accepted Submission(s): 237


    Problem Description
    Today is CRB's birthday. His mom decided to buy many presents for her lovely son.
    She went to the nearest shop with M Won(currency unit).
    At the shop, there are N kinds of presents.
    It costs Wi Won to buy one present of i-th kind. (So it costs k × Wi Won to buy k of them.)
    But as the counter of the shop is her friend, the counter will give Ai × x + Bi candies if she buys x(x>0) presents of i-th kind.
    She wants to receive maximum candies. Your task is to help her.
    1 ≤ T ≤ 20
    1 ≤ M ≤ 2000
    1 ≤ N ≤ 1000
    0 ≤ Ai, Bi ≤ 2000
    1 ≤ Wi ≤ 2000
     
    Input
    There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
    The first line contains two integers M and N.
    Then N lines follow, i-th line contains three space separated integers Wi, Ai and Bi.
     
    Output
    For each test case, output the maximum candies she can gain.
     
    Sample Input
    1 100 2 10 2 1 20 1 1
     
    Sample Output
    21
    Hint
    CRB's mom buys 10 presents of first kind, and receives 2 × 10 + 1 = 21 candies.
     
    Author
    KUT(DPRK)
     
    Source
     
    Recommend
    wange2014   |   We have carefully selected several similar problems for you:  5416 5415 5414 5413 5412
     
    大致三种方法:
    1.  01背包+完全背包
    先跑一遍01背包,价值为a+b的,然后再按价值为a的完全背包跑。
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<string>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define N 2005
     8 #define M 12
     9 
    10 int n,m;
    11 int f[N],w[N],a[N],b[N];
    12 
    13 int main()
    14 {
    15     int T;cin>>T;
    16     while(T--)
    17     {
    18         scanf("%d%d",&m,&n);
    19         for(int i=1;i<=n;i++)
    20         scanf("%d%d%d",&w[i],&a[i],&b[i]);
    21 
    22         memset(f,0,sizeof(f));
    23 
    24         for(int i=1;i<=n;i++)
    25         {
    26             for(int j=m;j>=w[i];j--)
    27             {
    28                 f[j]=max(f[j],f[j-w[i]]+a[i]+b[i]);
    29             }
    30             for(int j=w[i];j<=m;j++)
    31             {
    32                 f[j]=max(f[j],f[j-w[i]]+a[i]);
    33             }
    34 
    35         }
    36         cout<<f[m]<<endl;
    37     }
    38     return 0;
    39 }

    2. 完全背包的思路。每次有三种选择方案,1不选第i件物品,2选一个第2件物品,3选2个以上的第二件物品。

    用一个辅助数组g记录上一行(上一个i)的最大糖果数的值,因为完全背包空间是从小到大的,所以同一个i后面的空间会用到前面的的值,这也就是完全背包的内涵,但是用了辅助数组g,记录上一行的状态,就保证使用a+b不会用到前面的值。

    转移方程:f[j]=max3(f[j], f[j-w[i]]+a[i], g[j-w[i]]+a[i]+b[i]);

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<string>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define N 2005
     8 #define M 12
     9 
    10 int n,m;
    11 int w[N],a[N],b[N];
    12 int f[N];//f[j]表示j元钱可以得到的最大糖果数
    13 int g[N];//g[j]表示上一个i,j元可以得到的最大糖果数
    14 
    15 int max3(int a,int b,int c)
    16 {
    17     return max(a,max(b,c));
    18 }
    19 
    20 int main()
    21 {
    22     int T;cin>>T;
    23     while(T--)
    24     {
    25         scanf("%d%d",&m,&n);
    26         for(int i=1;i<=n;i++)
    27         scanf("%d%d%d",&w[i],&a[i],&b[i]);
    28 
    29         memset(f,0,sizeof(f));
    30         memset(g,0,sizeof(g));
    31 
    32         for(int i=1;i<=n;i++)
    33         {
    34             for(int j=w[i];j<=m;j++)
    35             {
    36                 f[j]=max3(f[j], f[j-w[i]]+a[i], g[j-w[i]]+a[i]+b[i]);
    37             }
    38             for(int j=0;j<=m;j++)
    39             {
    40                 g[j]=f[j];
    41             }
    42         }
    43         cout<<f[m]<<endl;
    44     }
    45     return 0;
    46 }

    3. 还是完全背包的思路,用dp[i][j][0]表示不取第i件物品,花费j得到的最大收益,dp[i][j][1]表示取第i件物品,花费j得到的最大收益,最终的结果就是max(dp[i][j][0],dp[i][j][1])。每次对于物品i,先得出不取它能得到的最大收益,然后再求取它能得到的最大收益。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    const int N = 2005;
    int dp[N][N][2];
    
    int main ()
    {
        int t;cin>>t;
        while ( t-- )
        {
            int m, n;
            scanf("%d%d", &m, &n);
            memset( dp, 0, sizeof(dp) );
            for ( int i = 1; i <= n; i++ )
            {
                int w, a, b;
                scanf("%d%d%d", &w, &a, &b);
                for ( int j = 0; j <= m; j++ )
                {
                    dp[i][j][0] = max( dp[i-1][j][0], dp[i-1][j][1] );
                }
                for ( int j = w; j <= m; j++ )
                {
                    dp[i][j][1] = max( dp[i][j - w][1] + a, dp[i][j - w][0] + a + b );
                }
            }
            printf("%d
    ", max( dp[n][m][0], dp[n][m][1] ));
        }
        return 0;
    }

     第一位空间可以压缩,把声明改成 int dp[N][2];最后结果改成max(dp[m][0],dp[m][1]).

    中间关键代码换成

        for ( int j = 0; j <= m; j++ )
        {
            dp[i][j][0] = max( dp[i-1][j][0], dp[i-1][j][1] );
        }
        for ( int j = w; j <= m; j++ )
        {
            dp[i][j][1] = max( dp[i][j - w][1] + a, dp[i][j - w][0] + a + b );
        }
  • 相关阅读:
    poj 3666 Making the Grade
    poj 3186 Treats for the Cows (区间dp)
    hdu 1074 Doing Homework(状压)
    CodeForces 489C Given Length and Sum of Digits...
    CodeForces 163A Substring and Subsequence
    CodeForces 366C Dima and Salad
    CodeForces 180C Letter
    CodeForces
    hdu 2859 Phalanx
    socket接收大数据流
  • 原文地址:https://www.cnblogs.com/wmxl/p/4749780.html
Copyright © 2011-2022 走看看