HDU 3591【多重背包】

题意:

有N种coin,给出每种coin的价值Vi,和小强拥有的个数Ci,小强去购物,要付m元,求小强和店员间交换货币时的最小个数货币,即小强付出coin个数加上店员找回coin个数。

解题思路:

背包题,先用二进制思想把coin合并成和种不同价值的货币,再进行01背包。

View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <string>
4 #include <cstring>
5 #include <algorithm>
6 #include <vector>
7 #include <map>
8
9 using namespace std;
10 const int MAXN = 100 + 10;
11 const int INF = 0x3f7f7f7f;
12 int V[MAXN];
13 int C[MAXN];
14
15 struct TCoin
16 {
17 int val, num;
18 }Coin[MAXN * MAXN * MAXN];
19
20 int DP[20000 + 10];
21 int main()
22 {
23 freopen("in.txt","r",stdin);
24 int N, T;
25 int caseNumber = 1;
26 while(scanf("%d%d", &N, &T) == 2 && (N || T))
27 {
28 printf("Case %d: ", caseNumber++);
29 for(int i = 1; i <= N; ++i)
30 scanf("%d", &V[i]);
31 for(int i = 1; i <= N; ++i)
32 scanf("%d", &C[i]);
33 int end = 1;
34 for(int i = 1, n; i <= N; ++i)
35 {
36 for(n = 1; n <= C[i]; n <<= 1)
37 {
38 Coin[end].val = n * V[i];
39 Coin[end].num = n;
40 ++end;
41 }
42 n >>= 1;
43 if(n < C[i])
44 {
45 Coin[end].val = (C[i] - n) * V[i];
46 Coin[end].num = C[i] - n;
47 ++end;
48 }
49 }
50 for(int i = 1; i <= 20000; ++i)
51 DP[i] = INF;
52 DP[0] = 0;
53 for(int i = 1; i < end; ++i)
54 {
55 for(int j = 20000; j >= Coin[i].val; --j)
56 {
57 if(DP[j] > DP[j - Coin[i].val] + Coin[i].num)
58 DP[j] = DP[j - Coin[i].val] + Coin[i].num;
59 }
60 }
61 int ans = INF;
62 for(int i = T; i <= 20000; ++i)
63 if(DP[i] + DP[i - T] < ans)
64 ans = DP[i] + DP[i - T];
65 if(ans == INF)
66 printf("-1\n");
67 else
68 printf("%d\n", ans);
69 }
70 return 0;
71 }



你可能感兴趣的:(HDU)