zoukankan      html  css  js  c++  java
  • POJ 2187 /// 凸包入门 旋转卡壳

    题目大意:

    求最远点对距离

    求凸包上的最远点对

    挑战263页

    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    using namespace std;
    const int N=5e5+5;
    const double eps=1e-10;
    
    int n;
    double add(double a,double b) {
        if(abs(a+b)<eps*(abs(a)+abs(b))) return 0;
        return a+b;
    }
    struct P {
        double x,y;
        P(){};
        P(double _x,double _y):x(_x),y(_y){};
        P operator - (P p) {
            return P(add(x,-p.x),add(y,-p.y)); };
        P operator + (P p) {
            return P(add(x,p.x),add(y,p.y)); };
        P operator * (double d) {
            return P(x*d,y*d); };
        double dot(P p) {
            return add(x*p.x,y*p.y); };
        double det(P p) {
            return add(x*p.y,-y*p.x); };
    }p[N];
    
    bool cmp(const P &a,const P &b){
        if(a.x==b.x) return a.y<b.y;
        return a.x<b.x;
    }
    vector <P> andrew()
    {
        sort(p,p+n,cmp);
        int k=0;
        vector <P> q(n*2);
        for(int i=0;i<n;i++) {
            while(k>1 && (q[k-1]-q[k-2]).det(p[i]-q[k-1])<=0) k--;
            // >0时q[k-1]才位于线段q[k-2]p[i]的左侧 形成下凸
            q[k++]=p[i];
        } /// 求下凸
        for(int i=n-2,t=k;i>=0;i--) {
            while(k>t && (q[k-1]-q[k-2]).det(p[i]-q[k-1])<=0) k--;
            q[k++]=p[i];
        } /// 求上凸
        q.resize(k-1);
        return q;
    }
    
    double dist(P a,P b) {
        return (a-b).dot(a-b);
    } // 点ab距离的平方
    
    void solve()
    {
        vector <P> q=andrew();
        int n=q.size();
        if(n==2) {
            printf("%.0f
    ",dist(q[0],q[1]));
            return ;
        }
        
        int i=0, j=0;
        for(int k=0;k<n;k++) {
            if(!cmp(q[i],q[k])) i=k; // 凸包的最左下
            if(cmp(q[j],q[k])) j=k; // 凸包的最右上
        }
    
        double ans=0;
        int si=i, sj=j;
        while(i!=sj || j!=si) { // 转半圈就能判断到所有对踵点对
            ans=max(ans,dist(q[i],q[j]));
            /*判断旋转
            <0两者未达到平行 那么先转i更易达到平行
            >0两者超过平行 那么转j更易达到平行
            */
            if((q[(i+1)%n]-q[i]).det(q[(j+1)%n]-q[j])<0)
                i=(i+1)%n;
            else j=(j+1)%n;
        }
        printf("%.0f
    ",ans);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        solve();
    
        return 0;
    }
    View Code
  • 相关阅读:
    kettle的转换组件
    kettle的输出组件
    js的touch事件的实际引用
    touchstart,touchmove,touchend触摸事件的小小实践心得
    Android使用ViewPager实现左右循环滑动及轮播效果
    jQuery漂亮图标的垂直导航菜单
    c#使用WebClient登录网站抓取登录后的网页
    从网页抓取数据的一般方法
    c#通过oledb获取excel文件表结构信息
    c#中高效的excel导入sqlserver的方法
  • 原文地址:https://www.cnblogs.com/zquzjx/p/9607857.html
Copyright © 2011-2022 走看看