• POJ 2079 Triangle 旋转卡壳求最大三角形


    求点集中面积最大的三角形...显然这个三角形在凸包上...

    但是旋转卡壳一般都是一个点卡另一个点...这种要求三角形的情况就要枚举底边的两个点 卡另一个点了...

    随着底边点的递增, 最大点显然是在以l(i,j)为底边进行卡壳旋转

    但分析了一下这种卡壳的复杂度到了O(n^2) 感觉不太靠谱...不知道有没有更强的方法...我感觉两个点卡的时候都是凸函数...不是很好卡的样子...如果我想到了我再更新这贴...

    /********************* Template ************************/
    #include <set>
    #include <map>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cassert>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <fstream>
    #include <numeric>
    #include <iomanip>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    
    #define EPS         1e-8
    #define MAXN        100005
    #define MOD         (int)1e9+7
    #define PI          acos(-1.0)
    #define INF         ((1LL)<<50)
    #define max(a,b)    ((a) > (b) ? (a) : (b))
    #define min(a,b)    ((a) < (b) ? (a) : (b))
    #define max3(a,b,c) (max(max(a,b),c))
    #define min3(a,b,c) (min(min(a,b),c))
    #define BUG         cout<<"BUG! "<<endl
    #define LINE        cout<<"------------------"<<endl
    #define L(t)        (t << 1)
    #define R(t)        (t << 1 | 1)
    #define Mid(a,b)    ((a + b) >> 1)
    #define lowbit(a)   (a & -a)
    #define FIN         freopen("in.txt","r",stdin)
    #pragma comment     (linker,"/STACK:102400000,102400000")
    
    // typedef long long LL;
    // typedef unsigned long long ULL;
    // typedef __int64 LL;
    // typedef unisigned __int64 ULL;
    // int gcd(int a,int b){ return b?gcd(b,a%b):a; }
    // int lcm(int a,int b){ return a*b/gcd(a,b); }
    
    /*********************   F   ************************/
    struct POINT{
        double x,y;
        POINT(double _x = 0, double _y = 0):x(_x),y(_y){};
        void show(){
            cout<<x<<" "<<y<<endl;
        }
    };
    POINT p[MAXN],s[MAXN];
    double dist(POINT p1,POINT p2){
        return((p1.x-p2.x) * (p1.x-p2.x) + (p1.y-p2.y) * (p1.y-p2.y));
    }
    double multiply(POINT sp,POINT ep,POINT op){
        return (sp.x-op.x) * (ep.y-op.y) - (ep.x-op.x) * (sp.y-op.y);
    }
    bool ptcmp(POINT a,POINT b){    // 极角排序cmp p[]为全局变量
        if(multiply(a,b,p[0]) == 0) return dist(p[0],a) < dist(p[0],b);
        return (multiply(a,b,p[0]) > 0);
    }
    int Graham_scan(POINT p[],POINT s[],int n){ //  返回凸包点的个数(修改版处理共线,无凸包)
        int i,k = 0,top = 2;
        for(i = 1; i < n ; i++)     //  取y最小且x最小的点为凸包起点
            if((p[i].y < p[k].y) || ((p[i].y == p[k].y) && (p[i].x < p[k].x)))
                k = i;
        swap(p[0],p[k]);            //  起点设置为p[0]
        if(n == 2) {                //  只有两个点不构成凸包的特判
            s[0] = p[0];
            s[1] = p[1];
            return 2;
        }
        sort(p+1,p+n,ptcmp);        //  极角排序
        for(i = 0 ; i < 3 ; i++)
            s[i] = p[i];            //  前三个点入栈
        if(n == 3 && multiply(s[0],s[1],s[2]) != 0) return 3;// 解决三个点且不共线的bug...
        while(multiply(s[0],s[top],s[top-1]) == 0 && i < n){ // 前三个点的共线特判
            s[top-1] = s[top];
            s[top] = p[i++];
        }
        if(i == n){                 //所有点都共线的特判
            s[1] = s[top];
            return 2;
        }
        for(; i < n ; i++){
            while(multiply(p[i],s[top],s[top-1]) >= 0)
                top--;
            s[++top] = p[i];
        }
        return top + 1;
    }
    double Triangle_area(POINT a,POINT b,POINT c){
        return fabs(multiply(a,b,c)/2);
    }
    double Rotation_Calipers(int len){      //旋转卡壳求凸包最大三角形
        double ans = 0;
        for(int i = 0 ; i < len ; i++){
            int j = (i + 1) % len;
            int k = (j + 1) % len;
            while(j != i && k != i){
                ans = max(ans,Triangle_area(s[i],s[j],s[k]));
                while(Triangle_area(s[i],s[j],s[(k+1)%len]) > Triangle_area(s[i],s[j],s[k]))
                    k = (k + 1) % len;
                j = (j + 1) % len;
            }
        }
        return ans;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("ou.txt","w",stdout);
        int n;
        while(~scanf("%d",&n)){
            if(n == -1) break;
            for(int i = 0 ; i < n ; i++)
                scanf("%lf%lf",&p[i].x,&p[i].y);
            int len = Graham_scan(p,s,n);
            double ans = Rotation_Calipers(len);
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    多西:一个创立了Twitter与Square的程序员
    越狱黑客Comex结束苹果实习生涯 将专注学校学习生活
    关于从页面中获取用户控件中的其它控件(如DropDownList)事件的方法
    如何更改VS2010的[默认开发语言]默认环境设置
    TRULY Understanding ViewState exactl
    .net平台下xml操作
    正则表达式学习2
    正则表达式学习3
    petshop 出现没有为 SQL 缓存通知启用数据库“MSPetShop4”
    利用ashx以XML返回的形式和ajax实现表格的异步填充
  • 原文地址:https://www.cnblogs.com/Felix-F/p/3251864.html
Copyright © 2020-2023  润新知