潜水员(gas)
【题目描述】
潜水员为了潜水要使用特殊的装备。他有一个带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)3ai,bi,ci(1≤ai≤21,1≤bi≤79,1≤ci≤800)3整数。这些各自是:第i个气缸里的氧和氮的容量及汽缸重量。
【输出】
仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。
【输入样例】
5 60
5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
【输出样例】
249
【解题思路】
1.判断该问题类型:由题意得,该题应使用dp求解。其中每个汽缸都有氧气和氮气两种气体,则该问题为二维费用的背包问题。
2.判断背包类型:显然,此题中每个汽缸只可取一次,则在使用二维数组的时候应逆序循环。
【代码实现】
1 #include <algorithm> 2 #include <cstring> 3 using namespace std; 4 int m, n; 5 int k; 6 int a[1005], b[1005], c[1005]; 7 int dp[1005][1005]; 8 9 int main() { 10 scanf("%d %d", &m, &n); 11 scanf("%d", &k); 12 for (int i = 1; i <= k; i++) { 13 scanf("%d %d %d", &a[i], &b[i], &c[i]); 14 } 15 16 memset(dp, 127, sizeof(dp)); // the started 17 dp[0][0] = 0; // don't forget it! 18 for (int i = 1; i <= k; i++) { 19 for (int j = m; j >= 0; j--) // O2 20 { 21 for (int h = n; h >= 0; h--) // N2,the amount of N2 is possible to be 0 22 { 23 int p = j + a[i]; 24 int q = h + b[i]; 25 if (p > m) { 26 p = m; 27 } 28 if (q > n) { 29 q = n; //even though p or q is huge,we just need to get the "n" "m" 30 //(用英语写也太费事了!蒟蒻不知道“值”的英文啊) 31 } 32 if (dp[p][q] > dp[j][h] + c[i]) { 33 dp[p][q] = dp[j][h] + c[i]; 34 } 35 } 36 } 37 } 38 printf("%d", dp[m][n]); 39 return 0; 40 } 41 /* 42 5 60 43 5 44 3 36 120 45 10 25 129 46 5 50 250 47 1 45 130 48 4 20 119 49 */
【题外话】
今天学校旁边的公园门口出了车祸,四死三伤。
下午上竞赛的时候得知袁隆平老爷子去了。
青海陕西云南也都发生了地震。
唉,我们这些尚留在这世间的生命啊,一定要好好活。