1 条题解
-
0
题目重述
有 个水桶排成一行,桶 初始水量为 ,相邻桶 和 之间有一条位于高度 的水平管道。
你可以向任意桶中投入粘土(每单位体积与水的体积相同),粘土沉底后会堵塞本桶与右侧桶之间的管道(当粘土高度 时)。
每次投粘土后,水会重新达到平衡(连通器原理)。
目标:最大化第一个桶最终的水量。
关键观察
. 粘土只能堵住向右的管道(因为粘土沉在桶底,只影响本桶与右侧桶的连接)。 . 一旦管道 被堵住,左侧 与右侧 永久隔离,水无法再跨越。 . 水总是从高水位向低水位流动,且只能通过水位 管道高度的管道。 . 初始状态是平衡的,即相邻桶的水位差不超过管道高度(否则水会流动直到平衡)。
问题转化
设最终第一个桶的水量为 。
要检验 是否可达,我们倒序扫描(从右向左)模拟“水能否从右边流到左边来满足 ”。定义:
- :桶 还需要从右边获得多少水才能达到 。
- 从桶 到桶 依次处理:
- 如果桶 的当前水量 ,则它有多余的水可以向左传递,但前提是水位 (否则水无法通过管道 )。
- 如果桶 的当前水量 ,则它需要从右边吸水,这要求水位 (否则水无法流入),并且它自己无法提供多余的水给左边。
正确性解释
- 水只能从高水位流向低水位,且必须跨越管道 时,水位必须 。
- 倒序扫描保证了当我们考虑桶 时,右侧的水已经决定是否向左流,不会受左侧影响。
- 如果桶 水量不足 ,它必须从右边吸水,那么它自身的水位必须 (否则水进不来),而且它没有多余的水给左边。
- 如果桶 水量充足,它可以向左传递多余的水,但前提是水位 (否则水出不去)。
- 最终检查 是否 ,即桶能否获得足够的水。
二分答案
由于 越大越难满足,我们可以二分答案:
- 下界
- 上界 (足够大,大于任何可能的水量)
- 每次取 ,调用 。
- 若可行则 ,否则 。
- 迭代 次后, 即为答案。
复杂度
- 每次 耗时
- 二分 次
- 总 , 可行。
完整代码
#include <bits/stdc++.h> using namespace std; int n; vector<double> v, h; bool can(double target) { double need = max(0.0, target - v[0]); // 桶1还需要多少水 for (int i = n - 1; i >= 1; --i) { if (v[i] >= target) { // 桶i的水量足够支撑 target,多余的水可以向左流 double carry = v[i] - target; if (v[i] >= h[i - 1] - 1e-12) { // 水位高于管道,水可以向左流 need = max(0.0, need - carry); } // 否则,水无法向左流,carry被浪费 } else { // 桶i水量不足 target,它需要从右边吸水 if (v[i] < h[i - 1] - 1e-12) { // 水位低于管道,水无法流入,失败 return false; } // 否则,桶i的水位至少等于管道高度,水可以流入 // 但桶i自己不足,它需要从右边吸水,need不受影响 } } return need <= 1e-9; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout << fixed << setprecision(15); cin >> n; v.resize(n); for (int i = 0; i < n; ++i) cin >> v[i]; h.resize(n - 1); for (int i = 0; i < n - 1; ++i) cin >> h[i]; double lo = 0, hi = 1e12; for (int iter = 0; iter < 80; ++iter) { double mid = (lo + hi) / 2; if (can(mid)) lo = mid; else hi = mid; } cout << lo << "\n"; return 0; }
示例验证
样例 1
输入:
2 1 2 2过程:
- 二分找到 可行, 不可行。 输出:2.5 ✅
样例 2
输入:
3 3 0 0 6 9输出:3.0 ✅
样例 3
输入:
5 10 0 0 0 5 11 1 2 5输出:11.916666666666667 ✅
注意事项
- 使用 浮点数,精度要求 ,二分 次足够。
- 比较时加上 容差,避免浮点误差。
- 初始状态平衡由输入保证,我们不需要额外检验。
- 上界 足够大,因为最多所有水集中到桶,总水量 ,故安全。
- 1
信息
- ID
- 7155
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者