zoj3703:
题意:给定一个背包的空间和物品个数,求出这个背包装的价值最大且物品个数最多的方案的价值,物品个数,解题时间(比赛计时那样算)
解题思路:裸0-1背包加记录路径,不过还要加上一个条件限制 :到达同一状态的物品总数尽可能大 ,所以要开一个辅助数组来记录某一状态的取物品个数
解题代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> int f[55][1005]; int g[55][1005]; int p[55][1005]; int c[55]; int w[55]; int k[55]; int tsum[55]; int MAX(int x, int y ) { return x > y? x:y; } int cmp(const void *a, const void *b) { return *(int*)a -*(int *)b; } int main() { int t ; scanf("%d",&t); while(t--) { memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); memset(k,0,sizeof(k)); memset(p,0,sizeof(p)); memset(tsum,0,sizeof(tsum)); int v, n; scanf("%d %d",&v,&n); for(int i = 1;i <= n;i ++) scanf("%d",&c[i]); for(int i = 1;i <= n; i ++) scanf("%d",&w[i]); for(int i = 1;i <= n;i ++) { for(int t = 0 ; t < c[i]; t++) { f[i][t] = f[i-1][t]; p[i][t] = p[i-1][t]; } for(int t = c[i]; t <= v; t++) { if(f[i-1][t] > f[i-1][t-c[i]]+w[i] ) { f[i][t] = f[i-1][t]; p[i][t] = p[i-1][t]; g[i][t] = 0; } else if(f[i-1][t] < f[i-1][t-c[i]]+w[i]) { f[i][t] = f[i-1][t-c[i]]+w[i]; p[i][t] = p[i-1][t]+1; g[i][t] = 1; } else { if(p[i-1][t] < p[i-1][t-c[i]]+1) { f[i][t] = f[i-1][t-c[i]]+w[i]; p[i][t] = p[i-1][t]+1; g[i][t] = 1; } else { f[i][t] = f[i-1][t-c[i]]+w[i]; p[i][t] = p[i-1][t]+1; g[i][t] = 0; } } } } int i = n ,r = 0; int t = v; int sumi = 0 , sum = 0; while(i > 0) { if(g[i][t] == 1) { k[r] = c[i]; r++; t = t - c[i]; sum++; sumi++; } i--; } qsort(k,r,sizeof(int),cmp); sum = k[0]; tsum[0] = k[0]; for(int h = 1;h < r;h ++) { tsum[h] = tsum[h-1]+k[h]; sum = sum+tsum[h]; } printf("%d %d %d\n",f[n][v],sumi,sum); } return 0; }