Cup 解题报告
题目描述
老师好不容易出了机房,端着他的杯子来到饮水机前,看着他那上大下小的水杯,突然想到了一个问题:如果我想接v体积的水,它的高度是多少呢?
老师的杯子可以看做是一个圆台,上面的圆的半径为R,下面的圆的半径为r,且R>=r, 杯子的高度为H。
输入: 四个数,分别为r,R,H,v,1 ≤ r, R, H ≤ 100; 0 ≤ V ≤ 1,000,000,000
输出: 一个数,表示v体积的水倒进去后的高度,保留6位小数。
输入样例: 100 100 100 3141562
输出样例: 99.999024
分析思路
方法一:二分法
我所采用的方法是二分。 倒入的水的高度范围一定在(0,H)之间。每次采用递归的方法去猜测水的高度,并用猜到的高度去求水的体积。如果比实际体积大那么就在低的二分区间继续查找,否则就在高的二分区间继续查找。直到二分的范围非常小,可以忽略不记的时候输出结果。
方法二:纯数学方法(感谢 CmYkRgB123):
圆柱情况是特殊的,特殊考虑。
如果是圆台,看它的轴截面图,可以看作为一个直角梯形的旋转体。梯形上底为R,下底为r,高为H。延长两腰中的一腰和高线,补全为直角三角形,设梯形高 线补全的长度增量为a,则直角三角形的两边分别为R和H+a。设倒水后水达到的高度为h,表面半径为r’,根据相似三角形
r/a=R/(H+a)=r'/(h+a)
再有圆台体积公式
1/3*pi*(r'^2*(h+a) - r^2*a)=V
两个式子联立可以用已知量表示出h。
完整代码(方法一)
//By Ceeji
//Date: 2009-4-7
//HAOI test 6 - Problem 4: Cup
//Type: 2 Div
//State: Sloved
Program cup;
Const inf='cup.in';
ouf='cup.out';
pi=3.1415926535898;
Var r1,r2,H,v,tmph,dtr,sdtr,tmpr,tmpv,allh:extended; // r1<=r2
Procedure init;
begin
assign(input,inf); reset(input);
assign(output,ouf); rewrite(output);
readln(r1,r2,h,v);
close(input);
dtr:=r2-r1;
if dtr<>0 then
allh:=h*r2/dtr-h;
end;
//Div 2 Do it;
Procedure try(minh,maxh:extended);
begin
if maxh-minh<0.00000001 then begin writeln((minh+maxh)/2:0:6); close(output); halt; end;
tmph:=(minh+maxh)/2;
sdtr:=(dtr*tmph)/h;
tmpr:=r1+sdtr;
tmpv:=1/3*(allh+tmph)*pi*tmpr*tmpr-1/3*(allh)*pi*r1*r1;
if tmpv<v then try(tmph,maxh) else try(minh,tmph);
end;
begin
init;
if r1=r2 then
begin
writeln(v/(pi*r1*r1):0:6);
close(output);
exit;
end;
try(0,h);
end.
题外话:我帮你整理了包括 AI 写作、绘画、视频(自媒体制作)零门槛 AI 课程 + 国内可直接顺畅使用的软件。想让自己快速用上 AI 工具来降本增效,辅助工作和生活?限时报名。
© 转载需附带本文链接,依据 CC BY-NC-SA 4.0 发布。