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