UVA - 11168 Airport (凸包+整理模板)

Time Limit: 3000MS     64bit IO Format: %lld & %llu

 Status uDebug

Description

Download as PDF

題意:

給平面上n個點,找一條直線,使得所有點在直線同側(或直線上),且到直線距離之和儘量小。

分析:

O(n)時間遍歷凸包的n條邊,計算每條邊對應的總距離,比較哪一個最小。

計算總距離可通過點到直線的距離公式,計算所有點的x座標與y座標之和,O(1)的計算出總距離。

改了一下模板,統一了一下。

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
const long long N=10005;
const long long mod=1e9;
const double eps=1e-10;
const double PI=acos(-1.0);
typedef long long ll;

struct Point {
    double x,y;
    Point (double x=0, double y=0):x(x),y(y) {}
};

typedef Point Vector;

Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y);}
Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y);}
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p);}
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p);}

bool operator < (const Point &a, const Point &b) {
    return a.x<b.x|| (a.x==b.x && a.y<b.y);
}

int dcmp(double x) {
    if (fabs(x)<eps) {
        return 0;
    } else {
        return x<0? -1:1;
    }
}

bool operator == (const Point& a, const Point &b) {
    return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
//點積 長度與夾角
double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y;}

double Length(Vector A) { return sqrt(Dot(A, A));}

double Angle(Vector A, Vector B) {return acos(Dot(A, B)/Length(A)/Length(B));}
//叉積
double Cross(Vector A, Vector B) { return A.x*B.y-A.y*B.x;}
double Area2(Point A, Point B, Point C) { return Cross(B-A, C-A);}

//rad是弧度
Vector Rotate(Vector A, double rad) {
    return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
}

//計算向量的單位法線,調用前確保A不是零向量
Vector Normal(Vector A) {
    double L=Length(A);
    return Vector(-A.y/L, A.x/L);
}

//直線交點,確保P+tv和Q+tw有唯一交點。當且僅當Cross(v,w)非0
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {
    Vector u=P-Q;
    double t=Cross(w, u)/Cross(v, w);
    return P+v*t;
}

//點到直線距離
double DistanceToLine(Point P, Point A, Point B) {
    Vector v1=B-A,v2=P-A;
    return fabs(Cross(v1, v2))/Length(v1);
}

//點到線段距離
double DistanceToSegment(Point P, Point A, Point B) {
    if (A==B) return Length(P-A);
    Vector v1=B-A, v2=P-A,v3=P-B;
    if (dcmp(Dot(v1, v2))<0) return Length(v2);
    else if (dcmp(Dot(v1, v3))>0) return Length(v3);
    else return fabs(Cross(v1, v2)) / Length(v1);
}

//計算點在線段上的投影
Point GetLineProjection(Point P, Point A, Point B) {
    Vector v=B-A;
    return A+v*(Dot(v, P-A)/Dot(v, v));
}

//線段相交判定(不計算端點)
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) {
    double c1=Cross(a2-a1, b1-a1), c2=Cross(a2-a1, b2-a1),
    c3=Cross(b2-b1, a1-b1), c4=Cross(b2-b1, a2-b1);
    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}

//計算端點是否在另外一條線段上
bool OnSegment(Point p, Point a1, Point a2) {
    return dcmp(Cross(a1-p, a2-p))==0 &&dcmp(Dot(a1-p, a2-p))<0;
}

//計算凸多邊形面積
double ConvexPolyonArea(Point* p,int n) {
    double area=0;
    for (int i=1; i<n-1; i++) {
        area+=Cross(p[i]-p[0], p[i+1]-p[0]);
    }
    return area/2;
}

//計算多邊形有向面積
double PolygonArea(Point *p,int n) {
    double area=0;
    for (int i=1; i<n-1; i++) {
        area+=Cross(p[i]-p[0], p[i+1]-p[0]);
    }
    return area/2;
}

//計算凸包 P272
int ConvexHull(Point *p, int n, Point* ch) {
    sort(p, p+n);
    int m=0;
    for (int i=0; i<n; i++) {
        while (m>1&&Cross(ch[m-1] - ch[m-2],p[i]-ch[m-2])<=0) {
            m--;
        }
        ch[m++]=p[i];
    }
    int k=m;
    for (int i=n-2; i>=0; i--) {
        while (m>k&&Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) {
            m--;
        }
        ch[m++]=p[i];
    }
    if (n>1) {
        m--;
    }
    return m;
}

double torad(double deg) {
    return deg/180 *acos(-1);
}

// 過兩點p1, p2的直線一般方程ax+by+c=0
// (x2-x1)(y-y1) = (y2-y1)(x-x1)
void getLineGeneralEquation(const Point& p1, const Point& p2, double& a, double& b, double &c) {
    a = p2.y-p1.y;
    b = p1.x-p2.x;
    c = -a*p1.x - b*p1.y;
}

int main() {
    int T,kase=0;
    double x[N],y[N];
    Point P[N],ch[N];
    cin>>T;
    while (T--) {
        kase++;
        int n,pc=0;
        double sx,sy;
        sx=sy=0;
        cin>>n;
        for (int i=0; i<n; i++) {
            scanf("%lf%lf",&x[i],&y[i]);
            P[pc++]=Point(x[i],y[i]);
            sx+=x[i];
            sy+=y[i];
        }
        sort(P, P+n);
        int m=unique(P, P+n)-P;
        m=ConvexHull(P, m, ch);
        double ans=1e9;
        if (m<=2) {
            ans=0;
        } else {
            for (int i=0; i<m; i++) {
                double a,b,c;
                getLineGeneralEquation(ch[i], ch[(i+1)%m], a, b, c);
                ans=min(ans,fabs(a*sx+b*sy+c*n)/sqrt(a*a+b*b));
            }
        }
        printf("Case #%d: %.3lf\n",kase,ans/n);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章