Water Levels in a Partitioned Aquarium
National Olympiad — National round (2015 season)
Submission name: aquarium.cpp
Problem summary
A 100×30×50 cm aquarium has a thin partition at x=B of height H. Water enters at x=F with flow A. For each position and time, find the local water level, capped at 50 cm.
Input
B H; F A; observation count L; then L pairs P T.
Output
Each water height rounded to three decimal places.
Constraints
0<B,F<100; 0<H<50; L<24; F and all P differ from B; flow and times are natural numbers.
Worked example
Input and output for the worked example discussed below.
Input
30 30 20 100 6 15 90 50 90 15 270 50 487 50 942 70 1502
Output
10.000 0.000 30.000 10.333 31.400 50.000
Solution analysis
- Convert time into volume V=A×T. If the tap is left of the partition, its side has width W=B; otherwise W=100−B. Its base area is 30W and the opposite base area is 30(100−W).
- Before V=30WH, only the tap side fills. Until V=3000H, that side stays at H while overflow fills the far side. Beyond that threshold, both sides share level V/3000. Clamp heights at the tank’s 50 cm wall.
- In the sample the tap side width is 30. At time 90 its level is 9000/900=10 while the far side remains empty. At time 487 the far level is (48700−27000)/2100≈10.333. By the final observation the aquarium has overflowed and the level is 50.
Why it works
Volume conservation and the partition height determine each phase. Water cannot cross before height H, cannot raise the near side above H while the far side is lower, and shares a common height once both reach H. Dividing the applicable volume by its base area yields each formula.
Watch out. Distinguish the tap side from the observation side. Include depth 30, use real division, print three decimals, and cap after overflow.
Commented C++17 solution
An independently written complete program with standard headers.
#include<algorithm>
#include<iomanip>
#include<iostream>
using namespace std;
int main(){
long double partition;
long double height;
long double tap;
long double flow;
cin>>partition>>height>>tap>>flow;
bool tapLeft=tap<partition;
long double width=tapLeft?partition:100-partition;
int queries;
cin>>queries;
cout<<fixed<<setprecision(3);
while(queries--){
long double position;
long double time;
cin>>position>>time;
long double volume=flow*time;
long double nearLevel;
long double farLevel;
if(volume<30*width*height){
nearLevel=volume/(30*width);
farLevel=0;
}
else if(volume<3000*height){
// The near side stays at the barrier while overflow fills the far side.
nearLevel=height;
farLevel=(volume-30*width*height)/(30*(100-width));
}
else{
nearLevel=volume/3000;
farLevel=nearLevel;
}
long double answer=(position<partition)==tapLeft?nearLevel:farLevel;
cout<<min(answer,50.0L)<<'\n';
}
}