• 背包问题之多重背包


    http://soj.sysu.edu.cn/show_problem.php?pid=1001&cid=1769

    其实感觉多重背包比01背包和完全背包都要难,每件物品的数量可能不止一件,还是求放入背包的物品的最大价值。

    在背包九讲中,给出的动态转移方程为:

    f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}

    但是感觉还是考虑边界问题比较烦人,所以我想的是把多重背包和之前的01背包联系起来......不知道行不行

    这里我写了一种一维dp数组的写法,在这题测试是tle的,因为这题的数据量太大,怎么解决后面再说......

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 
     7 int a[10];
     8 int w[10]={3, 5, 2, 6, 11, 8};
     9 double v[10]={0.01, 0.05, 0.10, 0.25, 0.50, 1};
    10 double dp[10005];
    11 //double dp[15][10005];
    12 
    13 int main()
    14 {
    15     int m;
    16     while(scanf("%d", &m) != EOF)
    17     {
    18         memset(dp, 0, sizeof(dp));
    19         int n=6;
    20         for(int i=0; i<n; i++)
    21             scanf("%d", &a[i]);
    22         //一维 
    23         for(int i=0; i<n; i++)
    24             for(int j=0; j<a[i]; j++) //相当于把物品分成一件一件
    25                 for(int k=m; k>=w[i]; k--)
    26                        dp[k] = max(dp[k-w[i]]+v[i], dp[k]);
    27         //二维  
    28         /* 
    29         for(int i=1; i<=n; i++)
    30             for(int j=0; j<=m; j++)
    31                 for(int k=0; k<=a[i]; k++)
    32                 {
    33                     if(j >= k*w[i])    
    34                         dp[i][j] = max(dp[i-1][j-k*w[i]]+k*v[i], dp[i][j]); 
    35                 }
    36               */
    37         printf("$%.2lf
    ", dp[m]);
    38         //printf("$%.2lf
    ", dp[n][m]);
    39     }
    40     return 0;
    41 }

    看注释那一行就相当于把相同的这几件物品分成一件件,然后套用01背包的方法来解决!

    那要怎么解决超时问题呢?

    用到了二进制划分的办法,分成1,2,4,8,16...64.....(剩下的)

    假如物品有12件,就分成1,2,4,5(这里的5就是剩下的),这样,如果我想拿7件,就用1+2+4来凑就好了,只用遍历3次,而不是7次!省了好多时间!

    最后还是用01背包解决!

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 
     7 int a[15];
     8 double dp[15000];
     9 int weight[15]={3, 5, 2, 6, 11, 8};
    10 double value[15]={0.01, 0.05, 0.10, 0.25, 0.50, 1};
    11 int w[15000];
    12 double v[15000];
    13 
    14 int main()
    15 {
    16     int N=6;
    17     int m;
    18     while(scanf("%d", &m) != EOF)
    19     {
    20         memset(dp, 0, sizeof(dp));
    21         int count = 0;
    22         for(int i=0; i<N; i++)
    23             scanf("%d", &a[i]);
    24             
    25         for(int i = 0; i < N; ++i)
    26         {
    27             for(int j = 1; j <= a[i]; j <<= 1) // 二进制拆分
    28             {
    29                 w[count] = j * weight[i];
    30                 v[count++] = j * value[i];
    31                 a[i] -= j;
    32             }
    33             if(a[i] > 0)
    34             {
    35                 w[count] = a[i] * weight[i];
    36                 v[count++] = a[i] * value[i];
    37             }
    38         }
    39         for(int i = 0; i < count; ++i)  // 使用01背包
    40             for(int j = m; j >= w[i]; j--)
    41                 dp[j] = max(dp[j-w[i]]+v[i], dp[j]);
    42         printf("$%.2lf
    ",dp[m]);
    43     }  
    44     return 0;
    45 }                                 
  • 相关阅读:
    testNg vs junit 4.X @Test
    lombok+slf4j+logback SLF4J和Logback日志框架详解
    IntelliJ IDEA 当pom.xml更新时,自动加载pom.xml
    运算符重载具体解释
    设计模式之十八:桥接模式(Bridge)
    无限层级的组织机构
    实战Jquery(一)--username校验
    Android错误之--Error retrieving parent for item: No resource found that matches the given name &#39;Theme.A
    hibernate 缓存
    android --多线程下载
  • 原文地址:https://www.cnblogs.com/dominjune/p/4409220.html
Copyright © 2020-2023  润新知