CF126A
Hot Bath 题解
题目简述
\(5\) 个正整数 \(t_{1}\),\(t_{2}\),\(x_{1}\),\(x_{2}\),$ t_{0} $。
这是一个简单的数学推理题。我们需要找到两个龙头的流速 \(y_1\) 和 \(y_2\),使得满足以下条件:
-
最终水温不低于 \(t_0\);
-
在满足上一条的前提下,水温尽可能接近 \(t_0\);
-
在满足上一条的前提下,总流速尽可能大。
思路实现
根据题目描述,我们可以得出以下结论:
-
如果 \(t_1 \geq t_0\),那么只需打开冷水龙头即可,此时 \(y_1\) 取最大值 \(x_1\),\(y_2\) 取 0。
-
如果 \(t_2 \leq t_0\),那么只需打开热水龙头即可,此时 \(y_1\) 取 0,\(y_2\) 取最大值 \(x_2\)。
接下来我们考虑 \(t_1 < t_0 < t_2\) 的情况。我们可以将问题分成两个子问题:
-
打开冷水龙头,关闭热水龙头:此时只需调节冷水龙头的流速 \(y_1\)。根据公式 \(\dfrac{t_1\times y_1}{y_1} = t_1\),我们可以得到此时的水温。如果水温小于 \(t_0\),则继续减小 \(y_1\) 的值;如果水温大于等于 \(t_0\),则记录下此时的流速和水温差。
-
打开热水龙头,关闭冷水龙头:此时只需调节热水龙头的流速 \(y_2\)。根据公式 \(\dfrac{t_2\times y_2}{y_2} = t_2\),我们可以得到此时的水温。如果水温大于 \(t_0\),则继续增大 \(y_2\) 的值;如果水温小于等于 \(t_0\),则记录下此时的流速和水温差。
最后,我们从两个子问题中找到水温差最小的情况即可。
Code:
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
long long t1, t2, x1, x2, t0;
cin >> t1 >> t2 >> x1 >> x2 >> t0;
double minDiff = 1e9; // 记录水温差的最小值
pair<int, int> ans; // 记录结果
// 子问题一:打开冷水龙头,关闭热水龙头
for (int y1 = x1; y1 >= 0; y1--) {
double temp = t1 * y1 / (double)y1; // 计算水温
if (temp < t0) {
break; // 水温小于 t0,继续减小 y1 的值
}
if (temp - t0 < minDiff) {
minDiff = temp - t0;
ans = make_pair(y1, 0);
}
}
// 子问题二:打开热水龙头,关闭冷水龙头
for (int y2 = x2; y2 >= 0; y2--) {
double temp = t2 * y2 / (double)y2; // 计算水温
if (temp >= t0) {
break; // 水温大于等于 t0,继续增大 y2 的值
}
if (t0 - temp < minDiff) {
minDiff = t0 - temp;
ans = make_pair(0, y2);
}
}
cout << ans.first << " " << ans.second << endl;
return 0;
}
该解法的时间复杂度为 \(O(x_1 + x_2)\),即龙头的最大流速和。
本文来自一名初中牲,作者:To_Carpe_Diem