当前位置: 代码迷 >> 综合 >> AcWing 1020. 潜水员 不同类型的背包问题(?)
  详细解决方案

AcWing 1020. 潜水员 不同类型的背包问题(?)

热度:81   发布时间:2023-11-23 13:36:33.0

AcWing 1020. 潜水员

潜水员为了潜水要使用特殊的装备。

他有一个带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。它们表示氧,氮各自需要的量。

第二行为整数 k 表示气缸的个数。

此后的 k 行,每行包括ai,bi,ci,3个整数。这些各自是:第 i 个气缸里的氧和氮的容量及气缸重量。

输出格式
仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。

数据范围
1≤m≤21,
1≤n≤79,
1≤k≤1000,
1≤ai≤21,
1≤bi≤79,
1≤ci≤800
输入样例:
5 60
5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
输出样例:
249

刚开始看到这个题我以为是二维背包问题的变形,于是我就在原有的二维背包问题多加了一个初始化条件,f[j][k]=0x3f,f[0][0]=0,然后改成min就可以了,但是结果是错的,后来看y总视频了解到,我这个只是求了体积和质量恰好为i,j的情况,然后我就看到了大佬的博文,我觉得还是非常不错的,拿来借鉴一下。

链接
根据大佬的解释,我是求的这个情况

体积恰好j,
当求价值的最小值:f[0][0] = 0, 其余是INF
当求价值的最大值:f[0][0] = 0, 其余是-INF

这道题y总的思路是,和二维的01背包差不多,但是在

for (int i = 0; i < n; i++) {
    for (int j = a[i]; j <= A; j++) {
    for (int k = b[i]; k <= B; k++) {
    if (j >= a[i] && k >= b[i]) {
    f[j][k] = min(f[j][k], f[j-a[i]][k-b[i]] + w[i]);}}}
}

01背包的原有基础上,在判断条件上更大了,因为就算是没有达到气缸的最大值(即i,j小于ai或bi),我们也需要一个物品去维持这个氧气为i,氢气为j的状态。

所以我们就把负数也作为一个参数放到这个数组里面去,但是我们二维数组是不允许出现负数下标的,其实我们知道,负数其实可以等同于0的(这一步我可能没怎么看懂。

最终代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;const int N=25,M=83;int f[N][M];
int m,n,k;int main(void)
{
    cin>>m>>n>>k;memset(f,0x3f,sizeof f);f[0][0]=0;for(int i=1;i<=k;i++){
    int ai,bi,ci;cin>>ai>>bi>>ci;for(int j=m;j>=0;j--)for(int k=n;k>=0;k--)f[j][k]=min(f[j][k],f[max(0,j-ai)][max(0,k-bi)]+ci);}cout<<f[m][n];
}