信息学奥赛一本通--1271--潜水员

潜水员

题目描述:

潜水员为了潜水要使用特殊的装备。他有一个带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个气缸里的氧和氮的容量及汽缸重量。

输出:

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


思路:

这其实就是一个二维费用背包问题,费用增加一维,只需状态增加一维即可。从而转化为普通的背包问题。唯一一点不同的是,当氧气和氮气超过需求时,直接等于需求。

这里有关于背包问题详解:背包问题详解

  • 设f[i][v][u]为前i件物品付出两种代价v和u时可获得的最大价值。
    状态转移方程:f[i][v][u]=max(f[i][v][u],f[i-1][v-a[i]][u-b[i]]+c[i])
  • 如01背包转化为一维问题一样,
    转化为二维f[v][u]=max(f[v][u],f[v-a[i]][u-b[i]]+c[i])

下面看代码

#include <iostream>
#include <cstring>
using namespace std;
int a[1005],b[1005],c[1005],dp[105][105];
int main()
{
	int m,n,k;
	cin>>m>>n;
	cin>>k;
	for(int i=0;i<k;i++)
	{
		cin>>a[i]>>b[i]>>c[i];
	}
	memset(dp,127,sizeof(dp));//把f初始化为一个很大的整数
	dp[0][0]=0;//o2为0,n2为0时,重量为0 
	for(int i=0;i<k;i++)
	{
		for(int j=m;j>=0;j--)
		{
			for(int l=n;l>=0;l--)
			{
				int d1=j+a[i];//O2  和01背包不同,它的a[i]和b[i]是可以超过的
				int d2=l+b[i];//N2
				if(d1>m) d1=m;//若氮 和氧含量超过需求,直接等于需求
				if(d2>n) d2=n;
				dp[d1][d2]=min(dp[d1][d2],dp[j][l]+c[i]); 
			}
		}
	}
	cout<<dp[m][n]<<endl;
	
	return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值