USACO Training 3.3 商店购物 By cellur925

Posted nopartyfoucaodong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USACO Training 3.3 商店购物 By cellur925相关的知识,希望对你有一定的参考价值。

题目传送门

这道题有着浓浓的背包气氛。所以我们可以这样想:可以把每个优惠方案都当做一个物品,每个单买所需要花的钱也当做一个物品。(也就是代码中的p结构体数组)而且基于此题的环境,这题是一个完全背包。
另外因为本题的算法比较亲民,至多买5种物品,每种物品最多买5个,所以我们可以(开创性地)使用五维背包。

状态:设f[i][j][k][a][b]表示买i件物品1,j件物品2,k件物品3,a件物品4,b件物品5所需要的最小价钱。(也就是说,我们熟悉的背包模板中f[i]中i的含义从体积在此题背景下变成了购买个数)

转移:f[i][j][k][a][b]=min(f[i][j][k][a][b],f[i-p[pos].cnt[1]][j-p[pos].cnt[2]][k-p[pos].cnt[3]][a-p[pos].cnt[4]][b-p[pos].cnt[5]]+p[pos].val);

边界:f[0][0]=0,其余为正无穷。(这种条件有时必要有时不必要,需要 具体分析)

 

将繁琐的数据输入处理后,我们就开始进行背包了。

但有一点需要注意,也是本题的重难点(之一)。也就是各个物品的编号给他转成1~5.但是其实数据已经约定了,购买方案中涉及到的产品应该也都是要买的。

所以每组数据涉及到的物品也就最多5个。

 

* 本题其实还可以用最短路做,这也是我之前比较倾向的算法。但是如何把各种购买方案映射好,却是一个难题。所以放弃了==

(@Sarah :每个节点的标号可以映射成一个篮子的物品个数情况,每一个优惠方式(包括以物品原价购买)表示一条边,权值就是花费,所以就是求一个从空篮子到目标篮子的最短路径。)

 Code

技术分享图片
 1 /*
 2 ID:cellur_2
 3 TASK:shopping
 4 LANG:C++
 5 */
 6 #include<cstdio>
 7 #include<algorithm>
 8 #include<map>
 9 
10 using namespace std;
11 const int inf=0x3f3f3f3f;
12 
13 int s,n,b,t;
14 int real[10];
15 int f[10][10][10][10][10];
16 struct goods{
17     int val;
18     int n;
19     int cnt[10];
20 }p[200];
21 map<int,int>m;
22 
23 void init()
24 {
25     for(int i=0;i<=5;i++)
26         for(int j=0;j<=5;j++)
27             for(int k=0;k<=5;k++)
28                 for(int a=0;a<=5;a++)
29                     for(int b=0;b<=5;b++)
30                         f[i][j][k][a][b]=inf;
31     f[0][0][0][0][0]=0;
32 }
33 
34 int main()
35 {
36     freopen("shopping.in","r",stdin);
37     freopen("shopping.out","w",stdout);
38     scanf("%d",&s);
39     for(int i=1;i<=s;i++)
40     {
41         scanf("%d",&n);
42         p[i].n=n;
43         for(int j=1;j<=n;j++)
44         {
45             int c=0,k=0;
46             scanf("%d%d",&c,&k);
47             if(m[c]==0) t++,m[c]=t;
48             p[i].cnt[m[c]]=k;
49         }
50         scanf("%d",&p[i].val);
51     }    
52     scanf("%d",&b);
53     for(int i=1;i<=b;i++)
54     {
55         s++;
56         int a=0,d=0,e=0;
57         scanf("%d%d%d",&a,&d,&e);
58         if(m[a]==0) t++,m[a]=t;
59         p[s].n=1,p[s].val=e,p[s].cnt[m[a]]=1;
60         real[m[a]]=d;
61     }
62     init();
63     for(int pos=1;pos<=s;pos++)
64         for(int i=p[pos].cnt[1];i<=real[1];i++)
65             for(int j=p[pos].cnt[2];j<=real[2];j++)
66                 for(int k=p[pos].cnt[3];k<=real[3];k++)
67                     for(int a=p[pos].cnt[4];a<=real[4];a++)
68                         for(int b=p[pos].cnt[5];b<=real[5];b++)
69                             f[i][j][k][a][b]=min(f[i][j][k][a][b],f[i-p[pos].cnt[1]][j-p[pos].cnt[2]][k-p[pos].cnt[3]][a-p[pos].cnt[4]][b-p[pos].cnt[5]]+p[pos].val);        
70     printf("%d
",f[real[1]][real[2]][real[3]][real[4]][real[5]]);
71     return 0;
72 }
View Code

 


以上是关于USACO Training 3.3 商店购物 By cellur925的主要内容,如果未能解决你的问题,请参考以下文章

USACO Training Section 3.1 Contact

等差数列 [USACO Training Section 1.4]

洛谷P2732 商店购物 Shopping Offers

USACO Training Section 1.1 题解(共4题)

Luogu2751 [USACO Training4.2]工序安排Job Processing

USACO Training完结感想