码迷,mamicode.com
首页 > 编程语言 > 详细

UVA 11168(凸包算法)

时间:2015-05-13 19:50:21      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:计算几何   凸包   一般式   点与直线的距离   

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34780

Problem

给N个点,画一条直线,所有点都在直线一侧(可以在直线上),且到达直线的平均距离最小(实际上就是总距离最小)。输出平均距离,N有10000级别,点坐标挺大。

Solution

首先,求一个凸包,枚举凸包点边,O(1)求出所有点到边的距离,维护最小值即可。

首先,为啥枚举凸包的边是对的?

其次,怎么O(1)求出,设直线返程为Ax+By+C=0, 点(x0,y0)到直线的距离为:Ax0+By0+CA2+B2,由于点都在直线一侧,所以(Ax0+By0+C)的符号都是一样的,只需预处理出ni=1xini=1yi,就好办啦。

怎么把求两点的一般式?最美的求法。

设y=kx+b,k=y1?y2x1?x2,b=y1-k*x1,kx-y+b=0,则A=k=y1?y2x1?x2,B=-1,C=b=y1?y1?y2x1?x2?x1,都乘上(x1-x2),得到:A=y1-y2,B=x2-x1,C=x1*y2-y1*x2(叉积,美不美?美不美!………..<–有病)

My code

//Hello. I‘m Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned int uin;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define MAXN
#define N 10100
#define M
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
const double eps=1e-9;
int dcmp(double x){
    if(fabs(x)<eps) return 0;
    else if(x<0) return -1;
    else return 1;
}
int n;
struct Point{
    double x,y;
    Point(){};
    Point(double xx,double yy){
        x=xx,y=yy;
    }
};
inline void readPointInt(Point &p){
    int x,y;
    x=read(),y=read();
    p=Point(x,y);
}
typedef Point Vector;
Vector operator+(const Vector a,const Vector b){
    return Vector(a.x+b.x,a.y+b.y);
}
Vector operator -(const Vector a,const Vector b){
    return Vector(a.x-b.x,a.y-b.y);
}
double operator *(const Vector a,const Vector b){
    return a.x*b.x+a.y*b.y;
}
double operator %(const Vector a,const Vector b){
    return a.x*b.y-a.y*b.x;
}
Vector operator*(const Vector a,const double b){
    return Vector(a.x*b,a.y*b);
}
Vector operator*(const double b,const Vector a){
    return Vector(a.x*b,a.y*b);
}
bool operator ==(const Vector a,const Vector b){
    return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);
}
inline bool comp(const Point a,const Point b){
    if(dcmp(a.x-b.x)) return a.x<b.x;
    else return a.y<b.y;
}
#define lenp res.size()
void Convex_Hull(Point *p,int n,vector<Point>&res){
    res.clear();
    sort(p,p+n,comp);
    for(int i=0;i<n;i++){
        while(lenp>1&&dcmp((res[lenp-1]-res[lenp-2])%(p[i]-res[lenp-1]))<=0) res.pop_back();
        res.push_back(p[i]);
    }
    int k=(int)lenp;
    for(int i=n-2;i>=0;i--){
        while(lenp>k&&dcmp((res[lenp-1]-res[lenp-2])%(p[i]-res[lenp-1]))<=0) res.pop_back();
        res.push_back(p[i]);
    }
    if(lenp>1) res.pop_back();
}
Point p[N];
double A,B,C;
inline void calABC(Point p1,Point p2){
    A=p1.y-p2.y;
    B=p2.x-p1.x;
    C=p1%p2;
}
int main(){
    int T=read();
    for(int kase=1;kase<=T;kase++){
        printf("Case #%d: ",kase);
        n=read();
        double totalx=0,totaly=0;
        for(int i=0;i<n;i++){
            readPointInt(p[i]);
            totalx+=p[i].x;
            totaly+=p[i].y;
        }
        if(n<=2){
            double ans=0.00000;
            printf("%.3f\n",ans);
            continue;
        }
        vector<Point>res;
        Convex_Hull(p,n,res);
        res.push_back(res[0]);//小技巧
        double ansdis=LL;
        for(int i=0;i<lenp-1;i++){
            calABC(res[i],res[i+1]);
            double up=fabs(A*totalx+B*totaly+C*n);
            double down=sqrt(A*A+B*B);
            double totaldis=up/down;
            if(!i) ansdis=totaldis;
            else ansdis=fmin(ansdis,totaldis);
        }
        printf("%.3f\n",ansdis/n);
    }
    return 0;
}

UVA 11168(凸包算法)

标签:计算几何   凸包   一般式   点与直线的距离   

原文地址:http://blog.csdn.net/uestc_peterpan/article/details/45695929

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!