容量有下限的二维费用背包问题—潜水员

原题链接:acwing1020. 潜水员
在这里插入图片描述

在这里插入图片描述
这是一个二维费用的背包问题,背包容量有下界限制(氧、氮),求背包能装的最小价值(气缸重量)
状态表示与状态转移如上图所示

f[i][j][k]表示考虑前i个物品,其氧气含量>=j,氮气含量>=k的最小价值
f[i][j][k]由可以两种状态转移而来:
当不选第i个物品时,f[i][j][k]=f[i-1][j][k],v1 v2为第i个物品的氧、氮含量
当选第i个物品时,   f[i][j][k]=f[i-1][j-v1][k-v2]+w
需要注意的是,当选第i个物品时,j<v1和k<v2的情况也是合法的,
当j<v1时j==v1
当k<v2时k==v2

背包问题考虑选的物品与体积关系时的初始化:

背包问题一共有三种物品与总体积的关系:最多、恰好、至少
1.体积最多为j,f[i]=0,v>=0,
从实际意义出发,当总体积为j时,f[0][j]表示一件物品都不选的最大价值,此时的价值为0
2.体积恰好是j,f[0]=0,f[i]=+(-)inf,v>=0,
体积恰好为j时,f[0][0]=0表示一件物品都不选,体积恰好为0的价值,因此f[0][0]=0,
f[0][j>0]表示一件物品都不选体积恰好为j>0时的最大(小价值),这种情况是不存在的,f[0][j]=+(-)inf(具体问题具体分析)
3.体积大于等于j,f[i]=0,f[i]=+(-)inf ,和上个体积恰好为j的分析类似,
不一样的情况是体积恰好为j那么所选物品的总体积只能是j,体积至少是j时,物品总体积可以超过j这时候也是合法的,需要考虑边际情况,也就是j-v<0也是合法的

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=22,M=80;

int f[N][M];

int main(){
    int n,m,k;
    cin>>n>>m>>k;
    memset(f,0x3f,sizeof f);
    f[0][0]=0;
    while(k--){
        int v1,v2,w;
        scanf("%d%d%d",&v1,&v2,&w);
        for(int i=n;i>=0;i--)
            for(int j=m;j>=0;j--){
                if(i<v1||j<v2) f[i][j]=min(f[i][j],f[max(i-v1,0)][max(j-v2,0)]+w);
                else f[i][j]=min(f[i][j],f[i-v1][j-v2]+w);
            }
                
    }
    cout<<f[n][m]<<endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chp的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值