WOJ 2068 潜水员

1 题面

1.1 描述

潜水员为了潜水要使用特殊装备。他有一个带两种气体的气缸:一个为氮气,一个为氧气。让潜水员下潜的深度需要各种数量的氧和氮。潜水员有一定数量的气缸。每个气缸都有重量和气体容量。潜水员为了完成他的工作需要特定的氧和氮。他完成工作所需气缸的总重最低限度是多少?

例如:潜水员有5个气缸。每行有三个数字为:氧、氮的量(升)和气缸的重量:

3 36 120
10 25 129
5 50 250
1 45 130
4 20 119

如果潜水员需要5升的氧和60升的氮则总重的最小值为249(1,2或4,5号气缸)。
你的任务就是计算潜水员为了完成他的工作需要的气缸的重量的最低值。

1.2 输入

第一行有2个整数m,n(1<=m<=21,1<=n<=79)。它们表示氧、氮各自需要的量。
第二行为整数k(1<=k<=1000)表示气缸的个数。
此后的k行,每行包括ai,bi,ci(1<=ai<=21,1<=bi<=79,1<=ci<=800)3整数
这些各自是:第i个气缸里的氧和氮的容量及气缸重量。

1.3 输出

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

1.4 样例

输入

5 60
5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119

输出

249

1.5 范围

1<=m<=21,1<=n<=79 1<=k<=1000 1<=ai<=21,1<=bi<=79,1<=ci<=800

1.6 来源

石室联中WOJ

2 分析

2.1 第一次分析

求最低值,有下限?
反过来不就好了,转换成扔罐子,而上限便是总量减去需要的量,便是一个裸的二维背包
然而…
21 ⋅ 1000 ⋅ 79 ⋅ 1000 21\cdot1000\cdot79\cdot1000 211000791000
M L E MLE MLE等着你

2.2 正解

别搞什么花里胡哨的转化了,直接正面思考
定义 f i , j f_{i,j} fi,j为满足 O 2 ≥ i , N 2 ≥ j O_2\ge i,N_2\ge j O2i,N2j的最小重量
那么转移方程显然:
f i , j = m i n { f i , j , f m a x { i − o 2 k , 0 } , m a x { j − n 2 k , 0 } + w k } f_{i,j}=min\{f_{i,j},f_{max\{i-o2_k,0\},max\{j-n2_k,0\}}+w_k\} fi,j=min{fi,j,fmax{io2k,0},max{jn2k,0}+wk}( m a x max max是为了避免下标为负)
两个 f o r for for枚举 i , j i,j i,j顺序随便(此处为01背包,反向枚举)
对于 k k k直接读一个处理一个(代码中下标有些不一样)

注意初始化memset(f,127,sizeof(f);f[0][0]=0;

3 代码

#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
	char ch;bool flag=0;
	while(!isdigit(ch=getchar()))if(ch=='-')flag=1;
	for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
	if(flag)n=-n;
}

int f[30][80];
int n, O2, N2, o2, n2, w;

int main(){
	Read(O2); Read(N2); Read(n);
	memset(f,127,sizeof(f));
	f[0][0] = 0;
	for(register int i=1; i<=n; i++){
		Read(o2); Read(n2); Read(w);
		for(register int j=O2; j>=0; j--)
			for(register int k=N2; k>=0; k--)
				f[j][k] = min(f[max(j-o2,0)][max(k-n2,0)]+w,f[j][k]);
	}
	cout<<f[O2][N2]<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值