USACO Section 3.3 Shopping Offers - 多重背包

来源:互联网 发布:知聊如何无限聊币 编辑:程序博客网 时间:2024/05/16 04:53

    

    看题目所给的数据范围...最多5种物品..每个物品最多拿5个..那么实际上总状态数最多也就6^5=7776种..并且每种状态可以表示成一个5位的6进制数..每种优惠方案也可以表示成一个5位的6进制数...想到了这里题目就简单了..由于优惠方案是可以多次使用的...所以做一次多重背包可以搞定...我为了方便..就把每个状态都转化成了十进制数...这样感觉更加直观和方便...

/*  ID: zzyzzy12   LANG: C++   TASK: shopping*/      #include<iostream>      #include<istream>  #include<stdio.h>      #include<string.h>      #include<math.h>      #include<stack>  #include<algorithm>      #include<queue>   #define oo 1000000000  #define ll long long  using namespace std;  struct node{      int num,a[6][6],p;     }s[105];struct node1{      int p,k;      }products[5];int n,m,dp[80000],t[1005],goal,_6jie[6];void make_dp(){      int h[5],i,j,y,x,temp;        memset(dp,0x7f,sizeof(dp));      if (!m) { dp[goal]=0; return; }      for (i=1;i<=goal;i++)       {              y=0;  x=i;              for (j=0;j<5;j++)              {                      temp=x%6;                     if (temp>products[j].k) goto A;                     y+=temp*products[j].p;                                      x/=6;              }               dp[i]=y;              A: ;      }         for (i=1;i<=n;i++)      {             temp=0;             for (j=1;j<=s[i].num;j++)  temp+=_6jie[t[s[i].a[j][0]]]*s[i].a[j][1];              if (dp[temp]>s[i].p) dp[temp]=s[i].p;              for (j=1;j<=goal-temp;j++)               if (dp[j+temp]-dp[j]>s[i].p)                   dp[j+temp]=dp[j]+s[i].p;       }}int main()  {        freopen("shopping.in","r",stdin);          freopen("shopping.out","w",stdout);        memset(products,0,sizeof(products));      scanf("%d",&n);      int i,j;      for (i=1;i<=n;i++)      {             scanf("%d",&s[i].num);             for (j=1;j<=s[i].num;j++) scanf("%d%d",&s[i].a[j][0],&s[i].a[j][1]);             scanf("%d",&s[i].p);      }      _6jie[0]=1;      for (i=1;i<6;i++) _6jie[i]=6*_6jie[i-1];      goal=0;      scanf("%d",&m);      for (i=0;i<m;i++)      {             scanf("%d",&j);             t[j]=i;             scanf("%d%d",&products[i].k,&products[i].p);             goal+=_6jie[i]*products[i].k;       }       make_dp();      printf("%d\n",dp[goal]);      return 0;     }  


原创粉丝点击