HDU 3033 I love sneakers! 我爱运动鞋 (分组背包+01背包,变形)

 

题意:

  有n<=100双鞋子,分别属于一个牌子,共k<=10个牌子。现有m<=10000钱,问每个牌子至少挑1双,能获得的最大价值是多少?

 

思路:

  分组背包的变形,变成了相反的,每组物品至少挑1件(分组背包问题是至多挑1件)。

  由于每个牌子至少买1双,那么可以先装一件最便宜的进去,如果有好的再更新(注意每次的容量下限)。而且同一双鞋子不能多次购买,这里要用01背包。对于当前容量cap,可能只装了某一牌子的一双鞋子(不一定最便宜),也可能装了多双,也可能只装了那双硬塞进去的最便宜的。

  注意点:有的店可是不一定有鞋子的;可能某个牌子连一双都买不起;可能买不全所有牌子。

 

   重写了次:

 1 //#include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <set>
 7 #include <deque>
 8 #include <map>
 9 #include <algorithm>
10 #include <vector>
11 #include <iostream>
12 #define pii pair<int,int>
13 #define back que[rear-1]
14 #define INF 0x3f3f3f3f
15 #define LL long long
16 #define ULL unsigned long long
17 using namespace std;
18 const double PI  = acos(-1.0);
19 const int N=10010;
20 int dp[11][N];
21 struct node
22 {
23     int p,v;
24 }r;
25 vector<node> vect[N];
26 inline int cmp(node a,node b){return a.p<b.p;}
27 bool cal(int n,int m,int k)
28 {
29     for(int i=1; i<=n; i++) //排序方便处理
30         sort(vect[i].begin(),vect[i].end(),cmp);
31     int sum=0;  //最便宜的鞋子价钱之和
32     for(int i=1; i<=k; i++)             //枚举组
33     {
34         if(vect[i].empty()) return false;   //无鞋
35 
36         node a=vect[i][0];
37         for(int j=m; j-a.p>=sum; j--)       //先装进去一个最便宜的
38             dp[i][j]=dp[i-1][j-a.p]+a.v;
39 
40         for(int t=1; t<vect[i].size(); t++) //考虑此组其他鞋
41         {
42             a=vect[i][t];
43             for(int j=m; j-a.p>=sum; j--)
44             {
45                 dp[i][j]=max(dp[i][j], dp[i-1][j-a.p]+a.v );    //注意点
46                 dp[i][j]=max(dp[i][j], dp[i][j-a.p]+a.v );
47             }
48         }
49         sum+=vect[i][0].p;
50         if(sum>m)           return false;   //买不起
51     }
52     return true;
53 }
54 
55 int main()
56 {
57     //freopen("input.txt", "r", stdin);
58     int w, n, m, k;
59     while(cin>>n>>m>>k)     //n双鞋子,m钱,k个牌子
60     {
61         memset(dp,0,sizeof(dp));
62         for(int i=0; i<=k; i++)    vect[i].clear();
63         for(int i=1; i<=n; i++)
64         {
65             scanf("%d%d%d", &w, &r.p, &r.v);
66             vect[w].push_back(r);   //分组保存
67         }
68         if(cal(n,m,k))    printf("%d\n",dp[k][m]);
69         else              printf("Impossible\n");
70     }
71     return 0;
72 }
AC代码

 

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n, m, k, w, dp[15][11000];
 4 struct node
 5 {
 6     int p,v;
 7 }r;
 8 vector< vector<node> > vect;
 9 inline int cmp(node a,node b){return a.p< b.p? 1: 0;}
10 int cal()
11 {
12     memset(dp,0,sizeof(dp));
13     int up=0;
14     for(int i=1; i<=k; i++)             //每组
15     {
16         r=vect[i][0];
17         for(int j=m; j>=up+r.p; j--)    //先装进去每组中最便宜的一个,有更好的再更新
18             dp[i][j]=dp[i-1][j-r.p]+r.v;
19 
20         for(int t=1; t<vect[i].size(); t++)//同组每种鞋
21         {
22             r=vect[i][t];
23             for(int j=m; j>=up+r.p; j--)  //每种容量。注意下限是前面所有店的最便宜鞋价的总和。最差也能买上前面所有店的最便宜的鞋子,其他都是无效的状态。
24             {
25                 dp[i][j]=max(dp[i][j], dp[i-1][j-r.p]+r.v );    //单独放。
26                 dp[i][j]=max(dp[i][j], dp[i][j-r.p]  +r.v );    //配合同组放。
27             }
28         }
29         up+=vect[i][0].p;   //更新下限
30     }
31     if(dp[k][m]>0)    return 1;
32     else    return 0;
33 }
34 void init()
35 {
36     vect.clear();
37     vector<node> tmp;
38     for(int i=0; i<=k; i++) vect.push_back(tmp);
39 }
40 
41 int main()
42 {
43     freopen("input.txt", "r", stdin);
44     while(cin>>n>>m>>k)
45     {
46         init();
47         for(int i=0; i<n; i++)
48         {
49             scanf("%d%d%d", &w, &r.p, &r.v);
50             vect[w].push_back(r);//分组保存
51         }
52         int big=0;
53         for(int i=1; i<=k; i++)
54         {
55             sort(vect[i].begin(), vect[i].end(), cmp);    //排个序,最低价的排在前面
56             if(!vect[i].empty())    big+=vect[i][0].p;  //坑在这,有的店完全没有鞋子!
57             else    big=0x7fffffff;//既然没有鞋子,置为无穷大,表示买不起。
58         }
59         if(big>m){printf("Impossible\n");continue;}   //每家店最便宜的鞋子都买不起
60         if(cal())    printf("%d\n",dp[k][m]);
61         else    printf("Impossible\n");
62     }
63     return 0;
64 }
AC代码

 

转载于:https://www.cnblogs.com/xcw0754/p/4521810.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值