您的位置:首页 > 其它

【hdu3033】分组背包(每组最少选一个)

2016-10-18 08:06 267 查看
【题意】

有S款运动鞋,一个n件,总钱数为m,求不超过总钱数且每款鞋子至少买一双的情况下,使价值最大。如果有一款买不到,就输出“Impossible"。

1<=N<=100 1 <= M<= 10000

【题解】

首先明显这是一个分组背包。

impossible 就直接看看每组最便宜的是否买得起。

因为每组最少选一个,所以我们可以这样dp:

f[k][j]表示当前扫到第k组,容量为j。

f[k][j]可由三个更新:

f[k][j]=f[k][j] 不选当前物品

f[k][j]=f[k-1][j-b[i]]+c[i] 选择当前物品,并且是在该组中第一次选物品

f[k][j]=f[k][j-b[i]]+c[i] 选择当前物品,并且不是在该组中第一次选

因为f[k][j]初始值为0,所以它最少都会买一样东西(由第二条更新得到)

1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 #include<queue>
7 #include<vector>
8 using namespace std;
9
10 const int N=11000,S=110;
11 int n,m,K,a
,b
,c
,mn[S],d[S][S],f[S]
;
12
13 int maxx(int x,int y){return x>y ? x:y;}
14 int minn(int x,int y){return x<y ? x:y;}
15
16 int main()
17 {
18     freopen("a.in","r",stdin);
19     while(scanf("%d%d%d",&n,&m,&K)!=EOF)
20     {
21         memset(d,0,sizeof(d));
22         memset(mn,63,sizeof(mn));
23         for(int i=1;i<=n;i++)
24         {
25             scanf("%d%d%d",&a[i],&b[i],&c[i]);
26             d[a[i]][++d[a[i]][0]]=i;
27             mn[a[i]]=minn(mn[a[i]],b[i]);
28         }
29         int x=0;
30         for(int i=1;i<=K;i++) x+=mn[i];
31         if(m<x) printf("Impossible\n");
32         else
33         {
34             memset(f,0,sizeof(f));
35             for(int k=1;k<=K;k++)
36             {
37                 for(int i=1;i<=d[k][0];i++)
38                 {
39                     x=d[k][i];
40                     for(int j=m;j>=b[x];j--)
41                     {
42                         f[k][j]=maxx(f[k][j],maxx(f[k-1][j-b[x]]+c[x],f[k][j-b[x]]+c[x]));
43                     }
44                 }
45             }
46             printf("%d\n",f[K][m]);
47         }
48     }
49     return 0;
50 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: