ACWing 潜水员
一、题解
-
对于dp的定义:重量总和的最低值(最低值的题目不会写, 刚看了题解才会写的)
-
背包的大小:m, n
-
dp数组是几维的:背包大小是m, n。这已经是二维了,在加上k种(普通背包必须有的),所以dp是三维的
遍历顺序:正常的背包,正序,逆序都可以 。这里采用和模板一样正序
-
初始化:这里没看题解不会,没做过最小值的题目。题解的做法,用memset吧dp设置为最大值,再吧dp[0][0][0] = 0。原因是当j == a[i]、s == b[i],就能从 dp[0][0][0]转移,以至于求解最小值
-
最难的转移方程:依我朴素的想法,一开始写就是 j < a[i] && s < b[i] 和j >= a[i] && s >= b[i] 和普通的背包一样。但是这里和背包不一样的是,背包空间不能 扩大,但是潜水员可以带 比相应容量(就是当前状态i, j)更大的氧气或氮气。就是这个 当前气缸提供的氧气或者当前气缸提供的氮气已经足够满足题目要求(就是够下潜,即使大也没关系)!
-
坑点 :数据范围1000,开三维数组,会爆数组空间。要优化。这里笔者用的是滚动数组
二、样例
输入:
5 60 5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
输出:
249
三、模板
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxl = 1e3 + 1;
int m, n, k, sum = 0;
int a[maxl], b[maxl], c[maxl];
int dp[2][maxl][maxl];
int main(){
memset(dp, 0x3f, sizeof(dp));
dp[0][0][0] = 0;
cin >> m >> n >> k;
for (int i = 0; i < k; i++)cin >> a[i] >> b[i] >> c[i];
for (int i = 0; i < k; i++){
for (int j = 0; j <= m; j++){
for (int s = 0; s <= n; s++){
if (j < a[i] && s < b[i]) dp[(i + 1) % 2][j][s] = dp[i % 2][j][s];
else if (j >= a[i] && s < b[i]) dp[(i + 1) % 2][j][s] = min(dp[i % 2][j][s], dp[i % 2][j - a[i]][0] + c[i]);
else if (j < a[i] && s >= b[i]) dp[(i + 1) % 2][j][s] = min(dp[i % 2][j][s], dp[i % 2][0][s - b[i]] + c[i]);
else dp[(i + 1) % 2][j][s] = min(dp[i % 2][j][s], dp[i % 2][j - a[i]][s - b[i]] + c[i]);
}
}
}
cout << dp[k % 2][m][n] << endl;
return 0;
}
四、最后
不同与模板题求最大值。这题求最小值,很一道很有价值的题。最后如果帮到你,请给个赞支持,谢谢!