SCUBADIV - Scuba diver 题解

题目传送门

更好的阅读体验

题目大意

潜水员有 n 个气缸,每个气缸能够提供容量为 oi 的氧气和容量为 di 的氮气,每个气缸的重量为 wi

给出潜水员所需要的氧气量和氮气量,求所需气缸的总重的最低限度是多少。

解题思路

对于每个气缸,有两种不同的费用:氧气和氮气,需要满足这两个条件,才能得到价值,也就是气缸的重量;所以可以看作是二维费用的背包问题。

将每个气缸的质量看做物品,把气缸的总重的最低限度看做背包。

枚举每个气缸,每次做二维费用的背包,如果当前的氧气或氮气超过了所需要的氧气或氮气,可以直接用需求量代替。

二维费用的背包:

划分阶段:

  • 以当前的氧气瓶为阶段;

状态表达:

  • fi,j 表示当所需的氧气量为 i,氮气量为 j 的时候气缸的最小重量;

状态转移:

  • 当不选第 i 个气缸时,不变,fj,k=fj,k

  • 当选第 i 个气缸时,减去当前的氧气和氮气,加上质量,fj,k=fjoi,kdi+wi

  • 这里注意,当 joikdi 小于零时,也就是选中当前的氧气和氮气后还有剩余的氧气和氮气,这种情况可以直接用 jk,所以可以特判一下,如果 joikdi 小于零,joikdi 等于 0

初始状态:

  • 因为当所需的氧气量为 0,氮气量为 0 的时候气缸的最小重量也是 0,所以 f0,0=0;要取最小值,所以其余全部为 inf

求解目标:fn,m

代码

最后输出不加换行会 WA!

AC 记录

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int INF=0x3f;
int q;
int main() {
	cin>>q;
	while(q--) {
		int n,m,idx;
		cin>>n>>m>>idx;
		int o[1005],d[1005],w[1005],f[25][80];
		for(ri i=1; i<=idx; i++)
			cin>>o[i]>>d[i]>>w[i];
		memset(f,INF,sizeof(f));
		f[0][0]=0;//初始状态
		for(ri i=1; i<=idx; i++)//阶段
			for(ri j=n; j>=0; j--)//氧气
				for(ri k=m; k>=0; k--) {//氮气
					int x=j-o[i],y=k-d[i];
					if(x<0)x=0;
					if(y<0)y=0;
					f[j][k]=min(f[j][k],f[x][y]+w[i]);
				}	
		cout<<f[n][m]<<'\n';//求解目标
	}
	return 0;
}
posted @   Ggsddu_zzy  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

喜欢请打赏

扫描二维码打赏

了解更多

点击右上角即可分享
微信分享提示