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.
当前页阅读量为: