• <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>
            算法學(xué)社
            記錄難忘的征途
            posts - 141,comments - 220,trackbacks - 0
            題目描述:
               在無限平面上有N(N<1,000)個圓。問一條直線最多可以“穿過”幾個圓,相切也算。

            算法分析:
               
               這樣的線一定是某兩個圓的切線。但是枚舉切線再O(N)判斷的話肯定會T。

               于是我們枚舉每個“中心圓”,求出這個圓與其他所有圓的切線。并極角排序。
               把每個切線想像成事件點,每個事件點要么增加一個圓,要么刪除一個圓。

               這樣的話對這個環(huán)行區(qū)間進行統(tǒng)計就可以了。
               
               求切線的時候,要判斷中心圓與其他圓的關(guān)系: 包含,內(nèi)切or外切,相交,被包含,分離。
               求切線其實只需要求一個角就可以了,不需要求完整的兩點式。

            #include<iostream>
            #include<cassert>
            #include<algorithm>
            #include<cstdio>
            #include<complex>
            #include<cmath>
            using namespace std;
            // template
            typedef complex<double> pnt;
            typedef pair<pnt,double> circle;
            const int N = 1005;
            const double eps = 1e-10;
            const double pi = acos(-1.0);
            inline bool eq(double a, double b){return abs(b-a) < eps;}
            inline double fix(double arg) {
                while(arg > pi) arg -= 2*pi;
                while(arg <= -pi) arg += 2*pi;
                return arg;
            }
            circle num[N];
            struct line {
                int id,c;
                double arg;
                line(){}
                line(int _id,int _c,double _arg) :
                id(_id) , c(_c), arg(_arg){
            //        cout<<"add: "<<id<<" "<<arg<<" "<<c<<endl;
                }
                bool operator < (const line& A) const{
                    return eq(arg , A.arg) ? c > A.c : arg < A.arg;
                }
            } Line[N<<2];
            // cut line
            #define ht first
            #define rs second
            inline void cut_line(const circle &A, const circle &B, int& ans, int& cnt,const int& id) {
                double d = abs(A.ht - B.ht) ;
                if(d <= abs(A.rs - B.rs)) {
                    if(d <= B.rs - A.rs ) {ans ++; return ;}
                    if(eq(d , A.rs - B.rs) ) {
                        Line[cnt++] = line(id, 1 , arg(B.ht - A.ht));
                        Line[cnt++] = line(id,-1 , arg(B.ht - A.ht));
                    }
                    return ;
                }
                double t;
                t = acos((A.rs - B.rs)/ d);
                double ag = arg(B.ht - A.ht);
                Line[cnt++] = line(id, 1 , fix(ag-t));
                Line[cnt++] = line(id,-1 , fix(ag+t));
                if(d > A.rs + B.rs + eps) {
                    double t = acos((A.rs + B.rs)/d);
                    Line[cnt++] = line(id, 1 , fix(ag+t));
                    Line[cnt++] = line(id,-1 , fix(ag-t));
                }
            }
            // solve
            bool vis[N];
            int work(int n, int len){
                int ans = 0, sum = 0;
                for(int i=0;i<n;i++){
                    vis[i] = 0;
                }
                for(int i=0;i<len+len;i++) {
                    int k = i%len;
                    int id = Line[k].id;
                    int c = Line[k].c;
                    if(c == 1){
                        assert(vis[id]==0);
                        vis[id] = 1; sum ++;
                    }
                    else if(c == -1) {
                        if(vis[id] == 1)
                            sum --, vis[id] = 0;
                    }
                    if(sum > ans ) ans = sum;
                }
                return ans;
            }
            // main
            int main(){
                int cas;
                cin >> cas;
                for(int oo=1; oo<= cas; oo++) {
                    int n,len = 0;
                    scanf("%d",&n);
                    for(int i=0;i<n;i++) {
                        int x,y,r;
                        scanf("%d%d%d",&x,&y,&r);
                        num[i] = make_pair(pnt(x,y) , r);
                    }
                    int ans = 0;
                    for(int s = 0; s < n; s ++) {
            //            cout<<"start: "<<s<<endl;
                        len = 0; int sum = 1;
                        for(int i=0;i< n; i++) if(i!=s) 
                            cut_line(num[s] , num[i], sum, len, i);
                        sort(Line, Line + len);
                        sum += work(n,len);
                        if(sum > ans) ans = sum;
                    }
                    printf("Case #%d: %d\n",oo, ans);
                }
            }
            posted on 2012-08-06 14:58 西月弦 閱讀(1244) 評論(0)  編輯 收藏 引用 所屬分類: 解題報告
            久久国产精品99精品国产| 亚洲国产精品狼友中文久久久 | 无码日韩人妻精品久久蜜桃 | 久久性生大片免费观看性| 久久伊人影视| 奇米影视7777久久精品| 久久久久久狠狠丁香| 久久亚洲天堂| AV无码久久久久不卡网站下载| 青青草原1769久久免费播放| 怡红院日本一道日本久久| 亚洲精品无码久久久久AV麻豆| 久久棈精品久久久久久噜噜| 国产 亚洲 欧美 另类 久久| 久久99热这里只有精品国产| 国产成人久久777777| 久久综合给合久久狠狠狠97色| 久久99精品国产麻豆蜜芽| 亚洲综合熟女久久久30p| 久久无码一区二区三区少妇| 97久久综合精品久久久综合| 久久久国产精华液| 日韩美女18网站久久精品| 国产 亚洲 欧美 另类 久久 | 亚洲欧洲久久久精品| 国产精品久久久久影视不卡| 浪潮AV色综合久久天堂| 色青青草原桃花久久综合| 久久精品国产一区| 99久久婷婷国产综合亚洲| 一本久久a久久精品vr综合| 伊人久久大香线蕉综合5g| 久久精品国产99国产精品| 中文字幕一区二区三区久久网站| 久久99久久99精品免视看动漫| 少妇久久久久久久久久| 77777亚洲午夜久久多人| 女同久久| 欧美精品乱码99久久蜜桃| 亚洲人成无码网站久久99热国产| 久久伊人亚洲AV无码网站|