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.
© 轉載需附帶本文連結,依 CC BY-NC-SA 4.0 釋出。