2013 多校第七场 hdu 4667 Building Fence(计算几何、凸包)

来源:互联网 发布:社工数据库 编辑:程序博客网 时间:2024/05/01 16:05

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4667

题目大意:给你n个圆,m个三角形,两两不重叠,问你把他们全都围起来的最短的篱笆的长度。

思路:我的做法是暴力,三角形不用处理,因为就三个点,圆的话,直接枚举角度,把它拆成点,然后上凸包,飘时限和精度。。。

经过不懈的努力之后,终于用G++ 900ms+ 飘过了,补充一句,C++TLE。。 = =

比赛的时候剩下一个半小时搞这道,因为搞计算几何的队友不在,木有搞过计算几何,也木有模板,明确暴力的思路后,就去网上乱找模板,结果找 cuo 了,最后还是没A。。 T^T

暴力代码如下:

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const double eps = 1e-8;const double PI = acos(-1.0);const int MAXN = 11111111 ;struct Point {    double x, y;    Point(){}    Point(double a,double b): x(a),y(b) {}    Point operator - (const Point& t) const {        Point tmp;        tmp.x = x - t.x;        tmp.y = y - t.y;        return tmp;    }    Point operator + (const Point& t) const {        Point tmp;        tmp.x = x + t.x;        tmp.y = y + t.y;        return tmp;    }    bool operator == (const Point& t) const {        return fabs(x-t.x) < eps && fabs(y-t.y) < eps;    }}GP,point[MAXN];struct Cir {Point ct;    double r;};inline double Cross(Point a, Point b, Point c) {// 叉积return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);}inline double PPdis(Point a, Point b) {// 点点距离    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}inline double PLdis(Point p,Point l1,Point l2){// 点线距离return fabs(Cross(p,l1,l2))/PPdis(l1,l2);}inline bool same_dir(Point a, Point b) {// 向量是否同向    return fabs(a.x*b.y-b.x*a.y) < eps && a.x*b.x > -eps && a.y*b.y > -eps;}bool dotOnSeg(Point p, Point s, Point e) {// 点是否在线段上    if ( p == s || p == e )// 看具体情况端点是否合法        return true;    return fabs((p-s).x*(p-e).y - (p-e).y*(p-s).x) < eps &&        (p.x-s.x)*(p.x-e.x)<eps && (p.y-s.y)*(p.y-e.y)<eps;}bool Intersect(Point p1, Point p2, Point p3, Point p4, Point& p) {// 直线相交double a1, b1, c1, a2, b2, c2, d;a1 = p1.y - p2.y; b1 = p2.x - p1.x; c1 = p1.x*p2.y - p2.x*p1.y;a2 = p3.y - p4.y; b2 = p4.x - p3.x; c2 = p3.x*p4.y - p4.x*p3.y;d = a1*b2 - a2*b1;if ( fabs(d) < eps )return false;p.x = (-c1*b2 + c2*b1) / d;p.y = (-a1*c2 + a2*c1) / d;return true;}bool cmpyx(Point a, Point b) {if ( a.y != b.y )return a.y < b.y;return a.x < b.x;}void Grahamxy(Point *p, int &n) {// 水平序(住:两倍空间)if ( n < 3 )return;int i, m=0, top=1;sort(p, p+n, cmpyx);for (i=n; i < 2*n-1; i++)p[i] = p[2*n-2-i];for (i=2; i < 2*n-1; i++) {while ( top > m && Cross(p[top], p[i], p[top-1]) < eps )top--;p[++top] = p[i];if ( i == n-1 )m = top;}n = top;}bool cmpag(Point a, Point b) {    double t = (a-GP).x*(b-GP).y - (b-GP).x*(a-GP).y;    return fabs(t) > eps ? t > 0 : PPdis(a, GP) < PPdis(b, GP);}void Grahamag(Point *p, int &n) {// 极角序    int i, top = 1;    GP = p[0];    for (i=1; i < n; i++) if(p[i].y<GP.y-eps || (fabs(p[i].y-GP.y)<eps && p[i].x<GP.x)) {        GP = p[i];    }    sort(p, p+n, cmpag);    for ( i=2; i < n; i++ ) {        while ( top > 0 &&  Cross(p[top], p[i], p[top-1]) < eps )            top--;        p[++top] = p[i];    }    p[++top] = p[0];    n = top;}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        int tot = 0;        double x,y,r;        for(int i = 0;i<n;i++)        {            scanf("%lf%lf%lf",&x,&y,&r);            for(double j = 0;j<2*PI;j += 0.0032)            {                point[tot++] = Point(x+r*cos(j),y+r*sin(j));            }        }        for(int i = 0;i<m;i++)            for(int j = 0;j<3;j++)            {                scanf("%lf%lf",&x,&y);                point[tot++] = Point(x,y);            }        Grahamxy(point,tot);        /*        printf("tot = %d\n",tot);        for(int i = 0;i<tot;i++)            printf("i = %d,x = %lf,y = %lf\n",i,point[i].x,point[i].y);        */        double ans = 0;        Point pre = point[0];        for(int i = 1;i<tot;i++)        {            ans += PPdis(point[i],pre);            pre = point[i];        }        ans += PPdis(point[0],pre);        printf("%.5f\n",ans);    }    return 0;}


原创粉丝点击