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 );
        }
  • 相关阅读:
    delphi 让子窗体显示最大化
    Delphi 中拖动无边框窗口的5种方法
    Delphi 非主窗体(即子窗体)在任务栏显示按钮
    电脑快捷键大全
    picpick快捷键
    is()
    animate()
    :animated
    css() 方法返回或设置匹配的元素的一个或多个样式属性。
    outerWidth()
  • 原文地址:https://www.cnblogs.com/wmxl/p/4749780.html
Copyright © 2011-2022 走看看