Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
潜水员为了潜水要使用特殊的装备。他有一个带2种气体的气缸:一个为氧气,一个为氮气。让潜水员下潜的深度需要各种的数量的氧和氮。潜水员有一定数量的气缸。每个气缸都有重量和气体容量。潜水员为了完成他的工作需要特定数量的氧和氮。他完
成工作所需气缸的总重的最低限度的是多少?
例如:潜水员有5个气缸。每行三个数字为:氧,氮的(升)量和气缸的重量:
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
如果潜水员需要5升的氧和60升的氮则总重最小为249(1,2或者4,5号气缸)。
你的任务就是计算潜水员为了完成他的工作需要的气缸的重量的最低值。
【输入格式】
第一行有2整数m,n(1<=m<=21,1<=n<=79)。它们表示氧,氮各自需要的量。
第二行为整数k(1<=n<=1000)表示气缸的个数。
此后的k行,每行包括ai,bi,ci(1<=ai<=21,1<=bi<=79,1<=ci<=800)3整数。这些各自是:第i个气缸里的氧和氮的容量及
汽缸重量。
【输出格式】
仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。
Sample Input
5 60 5 3 36 120 10 25 129 5 50 250 1 45 130 4 20 119
Sample Output
249
【题解】
对于每一个气缸。都有选或不选两种可能。也即0/1背包。但是这次不再是所用的花费不大于X的问题了。
而应该是刚好为X,或者到达了要求之后,大于等于X的问题。比如你要5单位的氧气。你不能说含有不超过
5单位氧气的最大花费,而应该说恰为5单位,或者给6单位也可以。大于5就直接让他等于5就可以了。
然后因为是0/1背包。更新的话要逆序更新。
这种恰好问题。要置其他f[i][j](二维费用)为一个很大的数,然后f[0][0] =0 ,表示0氧气,0氮气,
不需要气缸。所以重量为0;从f[0][0]开始得到其他值。
【代码】
#include <cstdio> int mo2,mn2,n,wo2[1010],wn2[1010],weight[1010],f[100][100]; void input_data() { scanf("%d%d",&mo2,&mn2); scanf("%d",&n); for (int i = 1;i <= n;i++) scanf("%d%d%d",&wo2[i],&wn2[i],&weight[i]); } void get_ans() { for (int i = 0;i <=mo2;i++) for (int j = 0;j <= mn2;j++) f[i][j] = 2100000000 / 3; //把其他f[i][j]置为一个很大的值 f[0][0] = 0; //0氧气0氮气的重量为0 for (int i = 1;i <= n;i++) for (int j = mo2 + wo2[i];j >= wo2[i];j--) //因为大于所需的值也是符合要求的 for (int k = mn2 + wn2[i];k >= wn2[i];k--) { int mm = j; if (j > mo2) //如果j是大于所需值,就让他为所需值就好 mm = mo2; int nn = k; if (k > mn2) nn = mn2; if (f[mm][nn] > f[j-wo2[i]][k-wn2[i]] + weight[i]) //尝试更新解。 f[mm][nn] = f[j-wo2[i]][k-wn2[i]] + weight[i]; } } void output_ans() { printf("%d",f[mo2][mn2]); //最后输出f[mo2][mn2]表示达到所需值,所花费的最少重量 } int main() { //freopen("F:\rush.txt","r",stdin); input_data(); get_ans(); output_ans(); return 0; }