zoukankan      html  css  js  c++  java
  • 【LOJ】 #2008. 「SCOI2015」小凸想跑步

    题解

    一道想法很简单的计算几何(由于我半平面交总是写不对,我理所当然的怀疑半平面交错了,事实上是我直线建错了)

    首先我们对于两个凸包上的点设为((x_0,y_0))((x_1,y_1))(逆时针)
    设这个点为(x,y)我们用叉积求一下面积
    可以得到
    ((x_0 - x)(y_1 - y) - (x_1 - x)(y_0 - y))
    (x_0 y_1 - x_1 y_0 + (y_0 - y_1)x + (x_1 - x_0)y)
    然后我们可以对于每个小三角形都求一个这样的式子,我们的约束就是(x,y),P_0 P_1的三角形面积最小
    最后会得到一个
    (Ax + By + C <= 0)的式子
    然后我们就可以建出直线来半平面交了,把x和C移到一边,讨论一下A是0或者B是0,然后讨论一下B的正负

    半平面交求出来的凸包面积除以原凸包面积就是答案了

    代码

    #include <bits/stdc++.h>
    #define MAXN 100005
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define eps 1e-8
    #define pii pair<int,int>
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {putchar('-');x = -x;}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    bool dcmp(db a,db b) {
        return fabs(a - b) < eps;
    }
    bool Gter(db a,db b) {
        return a > b + eps;
    }
    int N,tot;
    struct Point {
        db x,y;
        Point(){}
        Point(db _x,db _y) {
    	x = _x;y = _y;
        }
        friend Point operator + (const Point &a,const Point &b) {
    	return Point(a.x + b.x,a.y + b.y);
        }
        friend Point operator - (const Point &a,const Point &b) {
    	return Point(a.x - b.x,a.y - b.y);
        }
        friend Point operator * (const Point &a,const db &d) {
    	return Point(a.x * d,a.y * d);
        }
        friend Point operator / (const Point &a,const db &d) {
    	return Point(a.x / d,a.y / d);
        }
        friend db operator * (const Point &a,const Point &b) {
    	return a.x * b.y - a.y * b.x;
        }
        friend db dot(const Point &a,const Point &b) {
    	return a.x * b.x + a.y * b.y;
        }
    }P[MAXN];
    struct Seg {
        Point a,b;
        db d;
        Seg(){}
        Seg(Point _a,Point _b) {
    	a = _a;b = _b;d = atan2(b.y - a.y,b.x - a.x);
        }
        friend Point Cross_Point(const Seg &s,const Seg &t) {
    	db S1 = (s.a - t.a) * (t.b - t.a);
    	db S2 = (s.b - t.b) * (t.a - t.b);
    	return s.a + (s.b - s.a) * (S1 / (S1 + S2));
        }
    }S[MAXN * 4];
    bool cmp(Seg s,Seg t) {
        return Gter(t.d,s.d);
    }
    Point p[MAXN * 4];
    Seg q[MAXN];
    int ql,qr;
    void Process() {
        ql = 1,qr = 0;
        for(int i = 1 ; i <= tot ; ++i) {
    	while(ql < qr) {
    	    if(Gter(0.0,(S[i].b - S[i].a) * (p[qr - 1] - S[i].a))) --qr;
    	    else break;
    	}
    	while(ql < qr) {
    	    if(Gter(0.0,(S[i].b - S[i].a) * (p[ql] - S[i].a))) ++ql;
    	    else break;
    	}
    	q[++qr] = S[i];
    	if(ql < qr) {
    	    if(dcmp(q[qr].d,q[qr - 1].d)) {
    		if(Gter((q[qr].b - q[qr].a) * (q[qr - 1].a - q[qr].a),0.0)) --qr;
    		else q[qr - 1] = q[qr],--qr;
    	    } 
    	}
    	if(ql < qr) p[qr - 1] = Cross_Point(q[qr],q[qr - 1]);
        }
        while(ql < qr) {
    	if(Gter(0.0,(q[ql].b - q[ql].a) * (p[qr - 1] - q[ql].a))) --qr;
    	else break;
        }
        p[qr] = Cross_Point(q[qr],q[ql]);
        if(qr - ql + 1 >= 3) {
    	db res = 0.0,s = 0.0;
    	p[qr + 1] = p[ql];
    	for(int i = ql ; i <= qr ; ++i) {
    	    res += p[i] * p[i + 1]; 
    	}
    	for(int i = 0 ; i < N ; ++i) {
    	    s += P[i] * P[i + 1];
    	}
    	printf("%.4lf
    ",res / s);
        }
        else puts("0.0000");
    }
    void Solve() {
        read(N);
        db x,y;
        for(int i = 0 ; i < N ; ++i) {
    	scanf("%lf%lf",&x,&y);
    	P[i] = Point(x,y);
        }
        P[N] = P[0];
        for(int i = 0 ; i < N ; ++i) {
    	S[++tot] = Seg(P[i],P[i + 1]);
        }
        db C0 = P[0] * P[1],A0 = P[0].y - P[1].y,B0 = P[1].x - P[0].x;
        for(int i = 1 ; i < N ; ++i) {
    	db A = A0 - (P[i].y - P[i + 1].y);
    	db B = B0 - (P[i + 1].x - P[i].x);
    	db C = C0 - P[i] * P[i + 1];
    	if(dcmp(A,0.0) && dcmp(B,0.0) && Gter(C,0.0)) {puts("0.0000");return;}
    	if(dcmp(A,0.0)) {
    	    if(Gter(B,0.0)) S[++tot] = Seg(Point(10,-C / B),Point(-10,-C / B));
    	    else S[++tot] = Seg(Point(-10,-C / B),Point(10,-C / B));
    	}
    	else if(dcmp(B,0.0)) {
    	    if(Gter(A,0.0)) S[++tot] = Seg(Point(-C / A,-10),Point(-C / A,10));
    	    else S[++tot] = Seg(Point(-C / A,10),Point(-C / A,-10));
    	}
    	else {
    	    A = -A / B,C = -C / B;
    	    if(Gter(B,0.0)) S[++tot] = Seg(Point(10,A * 10 + C),Point(-10,-A * 10 + C));
    	    else S[++tot] = Seg(Point(-10,-A * 10 + C),Point(10,A * 10 + C));
    	}
        }
        sort(S + 1,S + tot + 1,cmp);
        Process();
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    需求分析之“客户隐形需求”
    JAVA版的SqlHelper【自学jdbc3个晚上的总结】
    NHibernate封装代码
    一步步认识NHibernate的延迟加载
    设置RichTextbox行间距
    .NET不可不读的书籍
    程序员的纠结
    CSS图片下载器
    从此告别CSDN
    C语言I博客作业02
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9155467.html
Copyright © 2011-2022 走看看