潜水员
潜水员
潜水员为了潜水要使用特殊的装备。
他有一个带 种气体的气缸:一个为氧气,一个为氮气。
让潜水员下潜的深度需要各种数量的氧和氮。
潜水员有一定数量的气缸。
每个气缸都有重量和气体容量。
潜水员为了完成他的工作需要特定数量的氧和氮。
他完成工作所需气缸的总重的最低限度的是多少?
例如:潜水员有 个气缸。每行三个数字为:氧,氮的(升)量和气缸的重量:
3 36 120 10 25 129 5 50 250 1 45 130 4 20 119
如果潜水员需要 升的氧和 升的氮则总重最小为 (, 或者 , 号气缸)。
你的任务就是计算潜水员为了完成他的工作需要的气缸的重量的最低值。
输入格式
第一行有 个整数 ,。它们表示氧,氮各自需要的量。
第二行为整数 表示气缸的个数。
此后的 行,每行包括 ,,, 个整数。这些各自是:第 个气缸里的氧和氮的容量及气缸重量。
输出格式
仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。
数据范围
,
,
,
,
,
输入样例:
5 60 5 3 36 120 10 25 129 5 50 250 1 45 130 4 20 119
输出样例:
249
解题思路
这是一个二维费用的背包问题。与之前的背包问题不同的是,这里要求费用至少是多少,费用至少是多少。
下面先给出一种状态表示,但根据这种状态表示来进行计算会超时。
表示从前个物品中选,氧气的容量恰好为,氮气的容量恰好为的所有方案的集合,属性是重量的最小值。状态转移方程为
其中和的最大上限均为,这是因为可能会有极端的数据,比如输入的氧气和氮气的容量全是“”或者“”。因此计算量就是,必然会超时,所以需要换一种状态表示。
状态表示还是,不过集合的含义变了,表示从前个物品中选,氧气的容量至少为,氮气的容量至少为的所有方案的集合,属性是重量的最小值。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 30, M = 90; 5 6 int f[N][M]; 7 8 int main() { 9 int n, m1, m2; 10 scanf("%d %d %d", &m1, &m2, &n); 11 12 memset(f, 0x3f, sizeof(f)); 13 f[0][0] = 0; // 一开始从前0个物品中选,也就是没有,氧气氮气的容量均为0,其他的状态俊不合法 14 for (int i = 1; i <= n; i++) { 15 int v1, v2, w; 16 scanf("%d %d %d", &v1, &v2, &w); 17 for (int j = m1; j >= 0; j--) { 18 for (int k = m2; k >= 0; k--) { // j和k均循环到0,即使k-v1<0或k-v2<0也是合法的 19 // 得到负数时说明只选择第i个物品就可以达到最小量j或k,意味着之前没有选含这个气体的物品,因此可以取0 20 f[j][k] = min(f[j][k], f[max(0, j - v1)][max(0, k - v2)] + w); 21 } 22 } 23 } 24 25 printf("%d", f[m1][m2]); 26 27 return 0; 28 }
代码中取的原因是,每个物品装有的气体的容量都大于等于,因此当某个气体减去当前瓶子的气体容量后小于,是等价于的,因为当容量小于意味着一个瓶子都没有选,而每个瓶子的装有气体的容量大于等于。
参考资料
AcWing 1020. 潜水员(算法提高课):https://www.acwing.com/video/379/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16513532.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-07-23 高精度模板