hdu 3756 || Dome of Circus || 2010 Northeastern European Regional Contest(三分)

題目hdu 3756 Dome of Circus連接 請搓

  1. 題意:
    在建一個已原點爲圓心的圓錐體。要求圓錐體要包括在給出n個在第一、二、三、四象限的所有點,並且使圓錐體體積最小,求出半徑和高。
  2. 思路:
    看了這個百度搜索排第一題解看懂了內容,但是這個和具體實現沒太大關係,頭都大了。一怒寫下這個自以爲比較簡單粗暴的博客。
    其實求最小體積,只和兩個變量有關,即圓半徑 r 和圓錐高 h, 而所求體積是正比於: r * r * h,這樣只需要計算出 r * r * h的最小值並且輸出 r 和 h 即可。
    由與最後結果的圓體至少會和一個點相交,而點固定的話,r大則h小而體積 v 越大, 反之,r 小 h 大 v 也大,所以在一定範圍內存在一個峯值(即所求答案),沒錯,要對 r 進行三分,每個三分的值需要對每個點計算h,取最大的h和r^2相乘得到體積,然後繼續三分,知道得到答案。又由 x、y、z 的範圍都不超過 1000,所以範圍是[max_r, 1e4] max_r是所有點的離軸的距離中最大的,而10000的確定。。。想不出就去補數學去。
  3. 複雜度:
    時間複雜度:O(n * 2 * lg3(10000-marx_r))
    空間複雜度:O(n)
  4. 代碼
/* ***********************************************
Author        :Ilovezilian
Created Time  :2015/8/3 21:02:56
File Name     :d.cpp
************************************************ */

#include <bits/stdc++.h>
#define fi(i,n) for(int i = 0; i < n; i ++)
#define fin(i,n1,n2) for(int i = n1; i < n2; i ++)
#define ll long long
#define INF 0x7fffffff
using namespace std;
const int N = 10010, mod = 1e9+7;
struct point{
    double x, y, z, r;
} p[N];
int n;

double cal(double r)
{
    double m = 0;
    fi(i,n) m = max(m, p[i].z / (r - p[i].r));
    return m * r;
}

void solve()
{
    scanf("%d", &n);
    double mh, mr;
    mh = mr = 0;
    fi(i,n)
    {
        scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z);
        p[i].r = sqrt(p[i].y * p[i].y + p[i].x * p[i].x);
        mr = max(mr, p[i].r);
        mh = max(mh, p[i].z);
    }

    double r = 2 * 1e+3, l = mr, midl, midr, la, ra;
    while(r - l > 1e-4)
    {
        midl = (r + 2 * l) / 3, midr = (l + 2 * r) / 3;
        la = cal(midl) * midl * midl, ra = cal(midr) * midr * midr;
        if(la < ra) r = midr;
        else l = midl;
    }
    double ans = (r + l) / 2;
    printf("%.3f %.3f\n", cal(ans), ans);
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int cas;
    scanf("%d", &cas);
    while(cas --) solve();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章