【9920】打包
Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
你现在拿到了许多的礼物,你要把这些礼物放进袋子里。你只有一个最多装下V 体积物品的袋子,你不能全部放进去。你也拿不动那么重的东西。你估计你能拿的最大重量为 G。现在你了解了每一个物品的完美值、重量和体积,你当然想让袋子中装的物品的完美值
总和最大,你又得计划一下了。
【输入格式】
第一行:V 和 G 表示最大重量和体积。
第二行:N 表示拿到 N 件礼物。
第三到N+2行:每行3个数 Ti Vi Gi 表示各礼物的完美值、重量和体积
对于20%的数据 N,V,G,Ti,Vi,Gi≤10
对于50%的数据 N,V,G,Ti,Vi,Gi≤100
对于80%的数据 N,V,G,Ti,Vi,Gi≤300
80%到100%的数据是N,V,G,Ti,Vi,Gi≤380 的离散随机数据。
【输出格式】
输出共一个数,表示可能获得的最大完美值。
Sample Input
6 5 4 10 2 2 20 3 2 40 4 3 30 3 3
Sample Output
50
【题解】
二维费用的0/1背包。
给0/1背包的f数组增加一维
f[i][j]表示花费1不超过i,花费2不超过j所能获得的最大完美值
f[i][j] = max(f[i][j] , f[i-w1[m]][j-w2[m]]+ c[m]);
记住0/1背包是逆序更新的就好了。
【代码】
#include <cstdio> #include <cstring> int mw1,mw2,n,c[400],w1[400],w2[400],f[400][400]; void input_data() { scanf("%d%d",&mw1,&mw2); scanf("%d",&n); for (int i = 1;i <= n;i++) scanf("%d%d%d",&c[i],&w1[i],&w2[i]); //输入有两个花费的物品的信息 } void get_ans() { memset(f,0,sizeof(f)); //初始化f数组为0 for (int i = 1;i <= n;i++) for (int j = mw1;j>=w1[i];j--) //枚举花费1和花费2 因为都是01背包所以都逆序。 for (int k = mw2;k >=w2[i];k--) if (f[j][k] < f[j-w1[i]][k-w2[i]] + c[i]) //如果能更新就更新 f[j][k] = f[j-w1[i]][k-w2[i]] + c[i]; } void output_ans() { printf("%d",f[mw1][mw2]); } int main() { //freopen("F:\\rush.txt","r",stdin); input_data(); get_ans(); output_ans(); return 0; }