poj 1170 Shopping Offers

题意:

给出若干种货物及其数量以及价格,然后给出一些优惠信息,一些货物组合在一起的价格一定比它们的原价加起来要低。

现在买到这些货物最少的钱(不能增加货物,即使钱会更少)。

思路:

最多有5种货物,每种货物最多5个。

那么就可以考虑压缩状态,6进制的状态压缩,这样就可以表示每种货物的状态。

然后,对于每一种优惠信息,可以在输入的时候就将其压缩为一种状态,节省大量的时间。

如果说对于所有的优惠信息都不满足的时候,那么就把原价当作优惠信息进行处理,这样即使所有的优惠信息都无法转移,那么原价是一定可以转移的。

dp[i] = min(d[i],dp[j]+cut[k]),i和j均满足输入限制,即所有物品的数量都小于等于输入。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <map>
 5 #include <vector>
 6 using namespace std;
 7 const int N = 50000;
 8 const int inf = 0x3f3f3f3f;
 9 struct node
10 {
11     int id,cnt;
12     node(){};
13     node(int a,int b)
14     {
15         id = a;
16         cnt = b;
17     }
18 };
19 int dp[N];
20 int num[20],prc[20],dic[200];
21 int ps[10];
22 map<int,int> mmp;
23 int js[200];
24 int main()
25 {
26     int n;
27     ps[0] = 1;
28     for (int i = 1;i < 10;i++) ps[i] = 6*ps[i-1];
29     scanf("%d",&n);
30     mmp.clear();
31     memset(dp,inf,sizeof(dp));
32     memset(js,0,sizeof(js));
33     for (int i = 0;i < n;i++)
34     {
35         int c,k,p;
36         scanf("%d%d%d",&c,&k,&p);
37         num[i] = k;
38         prc[i] = p;
39         mmp[c] = i;
40     }
41     int s;
42     scanf("%d",&s);
43     for (int i = 0;i < s;i++)
44     {
45         int t;
46         scanf("%d",&t);
47         for (int j = 0;j < t;j++)
48         {
49             int x,y;
50             scanf("%d%d",&x,&y);
51             js[i] += ps[mmp[x]] * y;
52         }
53         scanf("%d",&dic[i]);
54     }
55     for (int i = 0;i < n;i++)
56     {
57         for (int j = 1;j <= num[i];j++)
58         {
59             js[s] = ps[i] * j;
60             dic[s] = prc[i] * j;
61             s++;
62         }
63     }
64     dp[0] = 0;
65     int mmz = 0;
66     for (int i = 0;i < n;i++) mmz += ps[i]*num[i];
67     for (int i = 0;i <= mmz;i++)
68     {
69         for (int j = 0;j < s;j++)
70         {
71             if (dp[i] >= inf) continue;
72             int mz = i + js[j];
73             int tmp = mz;
74             int ct = 0;
75             bool f = 0;
76             while (tmp)
77             {
78                 if (tmp % 6 > num[ct]) f = 1;
79                 tmp /= 6;
80                 ct++;
81             }
82             if (f) continue;
83             dp[mz] = min(dp[mz],dp[i] + dic[j]);
84         }
85     }
86     printf("%d
",dp[mmz]);
87     return 0;
88 }
原文地址:https://www.cnblogs.com/kickit/p/8834928.html