• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-21  評論-10  文章-21  trackbacks-0
               這道題顯然考察積分,但有些積分是困難的(所以要平時多做題,能判斷哪些是自己能夠手算積出來的),
            能積出來當然盡量算出來,但對于那些困難的,就可以模擬積分的過程, 這里微元可以選擇橫截面,對于每一個橫截面的面積 S 是 一個弓形,這是好求的,再沿軸線方向積分卻困難了,邊看代碼邊解釋:

            waterloo的標程

             1 #include <stdio.h>
             2 #include <math.h>
             3 #include <assert.h>
             4 
             5 #define N 1000
             6 
             7 double s,delta,k,hb,db,hn,dn,h,V,hs,v;
             8 
             9 //求每個橫截面微元弓形的面積
            10 double area(double r, double s) {
            11    double t = db/2-s;
            12    double theta = t<r?acos(t/r):0;
            13    double wedge = theta * r * r;
            14    double triangles = r * cos(theta) * r * sin(theta);
            15    return wedge - triangles;
            16 }
            17 //求橫放 液面高度為 s時 的體積
            18 double volume(double s) {
            19    if (s*2 > db) return V - volume(db-s);
            20    double vb = area(db/2, s) * hb;
            21    double vn = area(dn/2, s) * hn;
            22    double vc = area(db/2, s) + area(dn/2, s);
            23    int i;
            24    /*================*/
            25    /*精彩的地方
            26 
            27      因為求不出那個定積分,所以只能分成 N 段逼近,當然 N 越大越準確,越大時間越多
            28      如果對被積函數的特性,如單調性, 斜率的變化情況快慢,大致曲線的形狀,越清楚,
            29      就越準確,像在這里,微元 area 以 r 作為變量,卻不是正比于 r^2,所以直接用
            30      for (i=1;i<N; i++) {
            31       vc +=  area((db + (dn-db)*i/N)/2, s);
            32       }
            33      vc *= (h-hn-hb)/N;
            34      去模擬那個積分過程效果就要差的多,N==5000時才能得到正確答案,而下面得方法 N==20
            35      就能得到正確答案,差距不是一點點!!
            36    */
            37    for (i=1;i<N;i+=2) {
            38       vc += 4 * area((db + (dn-db)*i/N)/2, s);
            39    }
            40    for (i=2;i<N;i+=2) {
            41       vc += 2 * area((db + (dn-db)*i/N)/2, s);
            42    }
            43    vc *= (h-hn-hb)/3/N;
            44    /*====================*/ 
            45    return vb + vn + vc;
            46 }
            47 
            48 doit(){
            49    int hnx = hn, hbx = hb, hx = h, dnx = dn;
            50    V = 2 * volume(db/2);//總的容積
            51    /*=======================*/
            52    //這段處理時修改瓶子,使得“瓶子”總是裝滿液體的,這樣就可以用同一個公式求出液體的體積
            53    if (k <= hb) {
            54       hn = 0;
            55       hb = k;
            56       h = k;
            57    } else if (k < h-hn) {
            58       dn = db + (dn-db) * (k-hb) / (h-hn-hb);
            59       hn = 0;
            60       h = k;
            61    } else {
            62       hn = hn - h + k;
            63       h = k;
            64    }
            65    v = 2 * volume(db/2);//液體的體積
            66    /*========================*/
            67    hn = hnx; hb = hbx; h = hx; dn = dnx;
            68    //將瓶子還原回來
            69    
            70    /*==========================*/
            71    //這個二分看得不怎么習慣
            72    s = db/2;
            73    for (delta=s/2;delta > .00001; delta /=2) {
            74       if (volume(s) > v) s -= delta;
            75       else s += delta;
            76    }
            77    /*======================*/
            78    printf("%0.2lf\n",s);
            79 }
            80 
            81 main(){
            82    while (6 == scanf("%lf%lf%lf%lf%lf%lf",&k,&hb,&db,&hn,&dn,&h)) {
            83       if (!(k||hb||db||hn||dn||h)) return;
            84       doit();
            85    }
            86 }
            87 

            my code:

             1 #include<iostream>
             2 #include<cmath>
             3 using namespace std;
             4 #define pi 3.1415926535897932384626433832795
             5 #define integral_Num 20//數據特殊才取20,照理還是取大點好
             6 #define eps 1e-8
             7 int sig(double x){return x < -eps ? -1 :  x > eps ; }
             8 double k ,hb ,db ,hn ,dn ,h, V;
             9 double area(double height, double r)
            10 
            11     if( sig(height - db/2 + r) < 0 ) return 0;
            12     if( sig(height - db/2 - r) >= 0 ) return pi*r*r;
            13     /*
            14     這里要確保acos的值為-1.0 ~1.0之間, 甚至為1.0+1e-10都不行, 
            15     此外 r 不能為 0,r == 0 的情況必須在上面就處理掉
            16     */
            17     double theta = acos( ( db/2 - height) / r );
            18     return r * r * theta - r * r * sin(theta) * cos(theta) ;
            19 }
            20 
            21 double volumn(double height)
            22 {
            23     int i;
            24     double 
            25         vb = area(height, db/2* hb,
            26         vn = area(height, dn/2* hn,
            27         vc = area(height, db/2+ area(height, dn/2);
            28     for(i = 1; i < integral_Num; i+=2)
            29         vc+=4 * area(height , 0.5 * db - 0.5 * (db - dn) * i / integral_Num );
            30     for(i = 2; i < integral_Num; i+=2)
            31         vc+=2 * area(height , 0.5 * db - 0.5 * (db - dn) * i / integral_Num );
            32     vc*=(h - hb - hn) / 3 / integral_Num;
            33     return vc+vn+vb;
            34 }
            35 void doit()
            36 
            37     double tk = k,  thb = hb,  tdb = db, thn = hn,  tdn = dn,  th = h;
            38     if(k <= hb){ hn=0; hb=k; h=hb; }
            39     else   if(k > h - hn) { hn=k+hn-h; h=k; }
            40      //要防止 h - hn - hb == 0 的情況運行到這一步
            41         else   {dn = db + (hb - k)*(db - dn)/(h - hn - hb); h=k; hn=0; }
            42   
            43     double v, l = 0 , r=db, mid;
            44         v=2*volumn(db/2);
            45         k = tk, hb = thb, db = tdb, hn = thn, dn = tdn, h = th;
            46         while(r - l >= 1e-3)
            47         { 
            48             mid=(r+l)/2;
            49             if(volumn(mid) > v) r  = mid;
            50             else l = mid;
            51         }
            52         printf("%.2lf\n",mid);
            53 }
            54 int main()
            55 
            56     /*freopen("C.1.dat","r",stdin);
            57     freopen("ans.txt","w",stdout);*/
            58     while(scanf("%lf%lf%lf%lf%lf%lf",&k, &hb, &db, &hn, &dn, &h) !=EOF)
            59     { 
            60         if(!(k || hb || db || hn || dn || h) )break;
            61         doit();
            62     }
            63 }
            64 




             

            posted on 2009-02-27 22:45 wangzhihao 閱讀(399) 評論(1)  編輯 收藏 引用

            評論:
            # re: pku 3289 Moonshine 2013-06-02 00:38 | ys
            這道題有積分公式,具體見poj 3929  回復  更多評論
              
            久久亚洲私人国产精品vA| 国产精品一区二区久久国产| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 亚洲?V乱码久久精品蜜桃 | 国产成人99久久亚洲综合精品| 久久精品国产99国产精品| 久久精品国产69国产精品亚洲| 久久精品青青草原伊人| 久久天天躁狠狠躁夜夜2020| 色综合久久久久网| 精品一区二区久久久久久久网站| 国产精品久久久久乳精品爆| 2021国产精品午夜久久| 久久夜色精品国产网站| 久久久久久九九99精品| 亚洲va久久久噜噜噜久久男同 | 亚洲午夜无码久久久久小说| 国产日韩欧美久久| 亚洲AV日韩AV天堂久久| 色偷偷88欧美精品久久久| MM131亚洲国产美女久久| 精品国产青草久久久久福利| 99久久婷婷国产一区二区| 草草久久久无码国产专区| 亚洲成色WWW久久网站| 亚洲国产精品综合久久网络| 国产精品永久久久久久久久久 | 久久综合视频网站| 国产精品丝袜久久久久久不卡 | 久久综合综合久久97色| 国产精品禁18久久久夂久| 亚洲中文字幕无码久久精品1| 久久这里只有精品18| 亚洲伊人久久综合影院| 欧美日韩精品久久久免费观看| 久久精品国产清自在天天线| 亚洲国产天堂久久综合网站| 青青青国产精品国产精品久久久久| 国产一级持黄大片99久久| 久久99精品久久久久婷婷| 久久精品国产久精国产|