zoukankan      html  css  js  c++  java
  • hdu-3449 Consumer---有依赖性质的背包

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=3449

    题目大意:

    fj打算去买一些东西,在那之前,他需要一些盒子去装他打算要买的不同的物品。每一个盒子有特定要装的东西(就是说如果他要买这些东西里的一个,他不得不先买一个盒子)。每一种物品都有自己的价值,现在FJ只有W元去购物,他打算用这些钱买价值最高的东西。

    思路:

    这是有依赖的背包,每件物品买之前必须买特定的盒子

    背包九讲:

    所以先对每一个箱子进行01背包,保存可以凑出的所有的花费和该花费的最大价值,这是一组中的所有状态,且只能取一个或者不取,背包转化成分组背包,然后就可以做了。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<vector>
     6 using namespace std;
     7 typedef pair<int, int> Pair ;
     8 const int INF = 0x3f3f3f3f;
     9 const int maxn = 1e5 + 10;
    10 int T, n, m, cases;
    11 struct node
    12 {
    13     int price;
    14     int num;
    15     int price_sum;
    16     int cost[11], value[11];
    17     int dp[1005];
    18 };
    19 node a[100];
    20 int dp[maxn];
    21 int main()
    22 {
    23     while(cin >> n >> m)
    24     {
    25         memset(dp, 0, sizeof(dp));
    26         memset(a, 0, sizeof(a));
    27         for(int i = 0; i < n; i++)
    28     {
    29         scanf("%d%d", &a[i].price, &a[i].num);
    30         a[i].price_sum = 0;
    31         for(int j = 0; j < a[i].num; j++)
    32         {
    33             scanf("%d%d", &a[i].cost[j], &a[i].value[j]);
    34             a[i].price_sum += a[i].cost[j];
    35         }
    36     }
    37     for(int i = 0; i < n; i++)//对,每个箱子预处理出所有可凑出的花费和该花费的最大价值
    38     {
    39         memset(a[i].dp, -1, sizeof(a[i].dp));
    40         a[i].dp[0] = 0;
    41         for(int j = 0; j < a[i].num; j++)
    42         {
    43             for(int k = a[i].price_sum; k >= a[i].cost[j]; k--)
    44                 if(a[i].dp[k - a[i].cost[j]] >= 0)a[i].dp[k] = max(a[i].dp[k], a[i].dp[k - a[i].cost[j]] + a[i].value[j]);
    45         }/*
    46         for(int j = 0; j <= a[i].price_sum; j++)
    47             cout<<a[i].dp[j]<<" ";
    48         cout<<endl;*/
    49     }
    50     for(int i = 0; i < n; i++)//枚举每一个的箱子
    51     {
    52         vector<Pair>d;
    53         for(int j = 0; j <= a[i].price_sum; j++)//将该箱子的所有状态存下来
    54         {
    55             if(a[i].dp[j] > 0)
    56                 d.push_back(Pair(j + a[i].price, a[i].dp[j]));
    57         }
    58         for(int v = m; v >= 0; v--)//枚举花费
    59         {
    60             for(int j = 0; j < d.size(); j++)//枚举改组的状态
    61                 if(v >= d[j].first)
    62                     dp[v] = max(dp[v], dp[v - d[j].first] + d[j].second);
    63         }
    64     }
    65     cout<<dp[m]<<endl;
    66     }
    67     return 0;
    68 }

    还有一种写法,在dp的时候把预处理和状态转化合并起来,时间复杂度降低了一点

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<vector>
     6 using namespace std;
     7 typedef pair<int, int> Pair ;
     8 const int INF = 0x3f3f3f3f;
     9 const int maxn = 1e5 + 10;
    10 int T, n, m, cases;
    11 int a[105];
    12 int dp[55][100005];
    13 struct node
    14 {
    15     int v, w;
    16 };
    17 vector<node>G[105];
    18 int main()
    19 {
    20     while(cin >> n >> m)
    21     {
    22         memset(dp, 0, sizeof(dp));
    23         for(int i = 1; i <= n; i++)G[i].clear();
    24         int tot, x, y;
    25         for(int i = 1; i <= n; i++)
    26         {
    27             scanf("%d%d", &a[i], &tot);
    28             for(int j = 0; j < tot; j++)
    29             {
    30                 scanf("%d%d", &x, &y);
    31                 G[i].push_back(node{x, y});
    32             }
    33         }
    34 
    35         for(int i = 1; i <= n; i++)//枚举每种箱子
    36         {
    37             for(int j = 0; j < a[i]; j++)dp[i][j] = -1;
    38             for(int j = a[i]; j <= m; j++)dp[i][j] = dp[i - 1][j - a[i]];//这里是确保先购买购物车
    39 
    40             for(int j = 0; j < G[i].size(); j++)//在购物车内进行01背包
    41             {
    42                 for(int k = m; k >= G[i][j].v; k--)
    43                 {
    44                     if(dp[i][k - G[i][j].v] != -1)
    45                         dp[i][k] = max(dp[i][k], dp[i][k - G[i][j].v] + G[i][j].w);
    46                 }
    47             }
    48             for(int j = 0; j <= m; j++)dp[i][j] = max(dp[i - 1][j], dp[i][j]);//和之前的值比较
    49         }
    50         cout<<dp[n][m]<<endl;
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    Swift
    Swift
    Swift
    Swift
    获取项目版本号与设置引导页的判断条件
    [iOS]简单的APP引导页的实现 (Swift)
    iOS
    文顶顶 iOS开发UI篇—UITabBarController简单介绍 iOS开发UI篇—UITabBarController简单介绍
    Swift开源项目精选
    Fuel 5.1安装openstack I版本号环境
  • 原文地址:https://www.cnblogs.com/fzl194/p/8833098.html
Copyright © 2011-2022 走看看