1 条题解
-
0
题解:Granny的威士忌冲洗问题
题目描述
Granny需要在Ness先生到访前,通过冲洗奶油罐尽可能多地清除罐中的威士忌。她最多可以进行k次冲洗操作,每次操作包括:
- 向罐中倒入一定量的水(可以为0)
- 充分混合罐中液体
- 倒出液体,使罐中剩余Vr体积的混合液体
已知条件:
- k:最大冲洗次数(1 ≤ k ≤ 100)
- Vb:桶中可用的雨水总量
- Vw:罐中初始威士忌体积
- Vr:每次倒出后罐中残留液体体积
- Vc:奶油罐的最大容量(Vc > Vw, Vr)
目标:确定最优的冲洗策略(每次使用的水量),使得最后一次冲洗后罐中残留的威士忌量最小。
解题思路
关键观察
- 稀释原理:每次冲洗都会稀释罐中的威士忌浓度。残留的威士忌量与每次冲洗使用的水量有关。
- 最优策略:要使最终威士忌量最小,应该尽可能多地使用水,并且尽可能早地使用大量水(因为早期冲洗的稀释效果会被后续冲洗放大)。
- 约束条件:
- 总用水量不超过Vb
- 任何时候罐中液体总量不超过Vc
数学建模
- 设第i次冲洗使用的水量为xi
- 每次冲洗后,罐中威士忌浓度为:当前威士忌量 / (当前总液体量)
- 倒出后,残留威士忌量为:Vr × 当前浓度
最优解性质
最优解具有以下特点:
- 尽可能使用全部k次冲洗机会(因为更多冲洗次数能更有效地稀释)
- 前k-1次冲洗使用尽可能少的水(刚好使罐中液体达到Vr),最后一次使用剩余所有可用水
- 或者当k=1时,直接使用全部可用水
算法选择
- 三分搜索:对于k>1的情况,可以三分搜索第一次冲洗的最优用水量x,使得剩余k-1次冲洗能均匀分配剩余水量(Vb-x)
- 直接计算:对于k=1的情况,直接使用min(Vb, Vc-Vw)的水量
实现步骤
- 检查是否可以不冲洗直接满足条件(Vr ≥ Vw)
- 对于k=1,直接使用最大可能水量
- 对于k>1:
- 前k-1次冲洗每次使用y = min((Vb-x)/(k-1), Vc-Vr)水量
- 使用三分搜索找到最优的x
代码实现
见原始C++代码,它实现了上述算法,包括:
- 输入处理
- 特殊情况处理(Vr ≥ Vw)
- 三分搜索寻找最优解
- 结果输出
复杂度分析
- 每个测试用例的时间复杂度:O(log(1/eps)),其中eps是精度要求(1e-9)
- 空间复杂度:O(1)
示例解释
样例输入:
2 15.0 25.0 1.0 50.0
解释:
- 可以进行2次冲洗,有15.0单位水可用
- 最优策略是:
- 第一次冲洗使用0.00水(仅倒出,不稀释)
- 第二次冲洗使用15.00水(最大可用量) 输出:
2 0.00 15.00
这个策略确保了最后一次冲洗后罐中残留的威士忌量最小。
代码实现
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std ; #define eqs 1e-9 int k ; double vb , vw , vr , vc ; double solve(double x) { double ans = vw/(vw+x) ; if( k > 1 ) { double y = min( (vb-x)/(k-1), vc-vr) ; for(int i = 1 ; i < k ; i++) ans *= vr/(vr+y) ; } return ans ; } int main() { while( scanf("%d", &k) != EOF ) { if(k == 0) break ; scanf("%lf %lf %lf %lf", &vb, &vw, &vr, &vc) ; if( vr-vw-vb > eqs ) { printf("0\n") ; continue ; } double low = max(0.0,vr-vw) , mid1 , mid2 , high = min(vb,vc-vw) ; while( low + eqs < high ) { mid1 = (low + high)/2.0 ; mid2 = (mid1 + high)/2.0 ; if( solve(mid1) > solve(mid2) ) { low = mid1 ; } else high = mid2 ; } printf("%d", k) ; printf(" %.2f", high) ; if( k > 1 ) high = min(vc-vr,(vb-low)/(k-1)) ; for(int i = 1 ; i < k ; i++) { printf(" %.2f", high) ; } printf("\n") ; } return 0 ; }
- 1
信息
- ID
- 2297
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者