题意:现在商场正在打折,打折的方式是同时买规定的的物品会比分开买便宜,现在告诉你打折的方式和要买的物品,求最少的钱,有个条件是不可以多买物品。
本题是典型的动态规划,对于动态规划问题,关键是找出其最优子结构,然后写出其递归式,然后,填表及可,另外注意各种边界条件。
对于本题,递归式可写为:
d[a1][a2][a3][a4][a5]=min(d[a1][a2][a3][a4][a5],d[a1-b1][ a2-b2][ a3-b3][ a4-b4][ a5-b5] + reduce[i] )
d[a1][a2][a3][a4][a5] 表示第 1 个物品买 a1 个,第 2 个物品买 a2 个,第 3 个物品买 a3 个,第 4 个物品买 a4 个,第 5 个物品买 a5 个的最小值。;b1、b2、b3、b4、b5 表示打折要买的物品数目。
/* ID: abc18711 LANG: C TASK: shopping */ #include <stdio.h> #include <string.h> struct good { int c; int k; int r; }; struct good a[6]; int offer[100][1000]; int reduce[100]; int d[6][6][6][6][6]; int num[100]; int min(int a,int b) { if(a < b) return a; else return b; } int main() { FILE *fin = fopen("shopping.in", "r"); FILE *fout = fopen("shopping.out", "w"); int s,n,i,j,a1,a2,a3,a4,a5,b1,b2,b3,b4,b5; fscanf(fin, "%d", &s); memset(offer, 0, sizeof(offer)); for(i=0;i<6;i++) a[i].c=a[i].k=0; for(i=1; i<=s; i++) { fscanf(fin, "%d", &num[i]); for(j=1; j<=num[i]; j++) { fscanf(fin, "%d%d", &a1, &a2); offer[i][a1]=a2; } fscanf(fin, "%d", &reduce[i]); } fscanf(fin, "%d", &n); for(i=1; i<=n; i++) { fscanf(fin, "%d%d%d", &a[i].c, &a[i].k, &a[i].r); } d[0][0][0][0][0]=0; for(a1=0;a1<=a[1].k;a1++) for(a2=0;a2<=a[2].k;a2++) for(a3=0;a3<=a[3].k;a3++) for(a4=0;a4<=a[4].k;a4++) for(a5=0;a5<=a[5].k;a5++) { d[a1][a2][a3][a4][a5]=a1*a[1].r+a2*a[2].r+a3*a[3].r+a4*a[4].r+a5*a[5].r; for(i=1;i<=s;i++) { if(num[i]>n) continue; b1=a1-offer[i][a[1].c]; b2=a2-offer[i][a[2].c]; b3=a3-offer[i][a[3].c]; b4=a4-offer[i][a[4].c]; b5=a5-offer[i][a[5].c]; if(b1<0||b2<0||b3<0||b4<0||b5<0) continue; d[a1][a2][a3][a4][a5]=min(d[a1][a2][a3][a4][a5],d[b1][b2][b3][b4][b5]+reduce[i]); } } fprintf(fout, "%d\n", d[a[1].k][a[2].k][a[3].k][a[4].k][a[5].k]); fclose(fin); fclose(fout); return 0; }