[关键字]:动态规划
[题目大意]:你要买n种商品,每种买k件。同时有一些组合购买的优惠方案,问最小花费。
//====================================================================================================
[分析]:因为最多才有五种商品,每种最多5件,所以五维的动态规划完全可以接受。至于方程太麻烦了,不写了,代码里很清楚……
[代码]:
/*
ID:procedure2
PROB:shopping
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=1684300900;
struct node
{
int sum,pay;
int next[10];
}a[100],d[100];
int s,n,m;
int b[1000];
int f[11][11][11][11][11];
void Init()
{
scanf("%d",&s);
for (int i=1;i<=s;i++)
{
scanf("%d",&a[i].sum);
//printf("%d\n",a[i].sum);
for (int j=1;j<=a[i].sum;j++)
{
int c,k;
scanf("%d%d",&c,&k);
if (!b[c]) b[c]=++n;
a[i].next[b[c]]=k;
}
scanf("%d",&a[i].pay);
//printf("%d %d %d %d %d %d %d\n",a[i].sum,a[i].next[1],a[i].next[2],a[i].next[3],a[i].next[4],a[i].next[5],a[i].pay);
}
//for (int i=1;i<=s;i++) printf("%d %d %d %d %d %d %d\n",a[i].sum,a[i].next[1],a[i].next[2],a[i].next[3],a[i].next[4],a[i].next[5],a[i].pay);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
int c,k;
scanf("%d%d",&c,&k);
if (!b[c]) b[c]=++n;
d[b[c]].sum=k;
scanf("%d",&d[b[c]].pay);
}
for (int i=1;i<=n;i++)
{
a[s+i].sum=1;
a[s+i].next[i]=1;
a[s+i].pay=d[i].pay;
}
s+=n;
//for (int i=1;i<=s;i++) printf("%d %d %d %d %d %d %d\n",a[i].sum,a[i].next[1],a[i].next[2],a[i].next[3],a[i].next[4],a[i].next[5],a[i].pay);
}
void Solve()
{
memset(f,100,sizeof(f));
f[0][0][0][0][0]=0;
for (int i1=0;i1<=d[1].sum;i1++)
for (int i2=0;i2<=d[2].sum;i2++)
for (int i3=0;i3<=d[3].sum;i3++)
for (int i4=0;i4<=d[4].sum;i4++)
for (int i5=0;i5<=d[5].sum;i5++)
if (f[i1][i2][i3][i4][i5]!=INF)
for (int j=1;j<=s;j++)
f[i1+a[j].next[1]][i2+a[j].next[2]][i3+a[j].next[3]][i4+a[j].next[4]][i5+a[j].next[5]]
=min(f[i1+a[j].next[1]][i2+a[j].next[2]][i3+a[j].next[3]][i4+a[j].next[4]][i5+a[j].next[5]],f[i1][i2][i3][i4][i5]+a[j].pay);
printf("%d\n",f[d[1].sum][d[2].sum][d[3].sum][d[4].sum][d[5].sum]);
}
int main()
{
freopen("shopping.in","r",stdin);
freopen("shopping.out","w",stdout);
Init();
Solve();
return 0;
}