• 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
  • 相关阅读:
    并发编程概述
    学习笔记-ResNet网络
    学习笔记-反向传播算法
    学习笔记-canny边缘检测
    学习笔记-霍夫变换
    GitHub访问速度慢的一种优化方法
    C#开源定时回调库PETimer的使用
    C#开源网络通信库PESocket的使用
    XML在C#与Unity3D中的实战运用
    Unity本地持久化类Playerprefs使用详解
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9635395.html
Copyright © 2020-2023  润新知