zoukankan      html  css  js  c++  java
  • 【BZOJ 1038】【ZJOI 2008】瞭望塔

    http://www.lydsy.com/JudgeOnline/problem.php?id=1038

    半平面交裸题,求完半平面后在折线段上的每个点竖直向上和半平面上的每个点竖直向下求距离,统计最小的值作为答案即可。

    1A!!!斯巴达!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 303;
    
    struct Point {
    	double x, y;
    	Point(double _x = 0, double _y = 0) : x(_x), y(_y) {}
    } t[N], p[N];
    struct Line {
    	Point p, v; double ang;
    	Line(Point _p = Point(0, 0), Point _v = Point(0, 0), double _ang = 0) : p(_p), v(_v), ang(_ang) {}
    	bool operator < (const Line &x) const {
    		return ang < x.ang;
    	}
    } l[N], q[N];
    
    Point operator + (Point a, Point b) {return Point(a.x + b.x, a.y + b.y);}
    Point operator - (Point a, Point b) {return Point(a.x - b.x, a.y - b.y);}
    Point operator * (Point a, double x) {return Point(a.x * x, a.y * x);}
    Point operator / (Point a, double x) {return Point(a.x / x, a.y / x);}
    
    int dcmp(double x) {return fabs(x) < 1e-8 ? 0 : (x < 0 ? -1 : 1);}
    double Dot(Point a, Point b) {return a.x * b.x + a.y * b.y;}
    double Cross(Point a, Point b) {return a.x * b.y - a.y * b.x;}
    double sqr(double x) {return x * x;}
    double dis(Point a, Point b) {return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
    
    bool onleft(Point a, Line b) {return dcmp(Cross(a - b.p, b.v)) < 0;}
    Point intersection(Line a, Line b) {
    	Point u; double t;
    	u = a.p - b.p;
    	t = Cross(b.v, u) / Cross(a.v, b.v);
    	return a.p + (a.v * t);
    }
    
    int n, head = 1, tail = 2;
    double ans;
    
    void mkhalf() {
    	q[1] = l[1]; q[2] = l[2];
    	p[1] = intersection(q[1], q[2]);
    	for(int i = 3; i < n; ++i) {
    		while (head < tail && !onleft(p[tail - 1], l[i])) --tail;
    		while (head < tail && !onleft(p[head], l[i])) ++head;
    		q[++tail] = l[i];
    		if (dcmp(Cross(q[tail].v, q[tail - 1].v) == 0)) {
    			--tail;
    			if (onleft(l[i].p, q[tail])) q[tail] = l[i];
    		}
    		if (head < tail) p[tail - 1] = intersection(q[tail - 1], q[tail]);
    	}
    //	while (head < tail + 1 && !onleft(p[tail - 1], q[head])) --tail;
    }
    
    double cal(int num) {
    	Point j;
    	double x = t[num].x, y = t[num].y;
    	if (x <= p[head].x) {
    		j = intersection(q[head], Line(t[num], Point(0, 1)));
    		return j.y - y;
    	}
    	if (x >= p[tail - 1].x) {
    		j = intersection(q[tail], Line(t[num], Point(0, 1)));
    		return j.y - y;
    	}
    	int left = head, right = tail - 1, mid;
    	while (left < right) {
    		mid = (left + right + 1) >> 1;
    		if (p[mid].x > x) right = mid - 1;
    		else left = mid;
    	}
    	j = intersection(q[left + 1], Line(t[num], Point(0, 1)));
    	return j.y - y;
    }
    
    double cal2(int num) {
    	Point j;
    	double x = p[num].x, y = p[num].y;
    	int left = 1, right = n, mid;
    	while (left < right) {
    		mid = (left + right + 1) >> 1;
    		if (t[mid].x > x) right = mid - 1;
    		else left = mid;
    	}
    	j = intersection(Line(t[left], t[left + 1] - t[left]), Line(p[num], Point(0, -1)));
    	return y - j.y;
    }
    
    int main() {
    	scanf("%d", &n);
    	for(int i = 1; i <= n; ++i) scanf("%lf", &t[i].x);
    	for(int i = 1; i <= n; ++i) scanf("%lf", &t[i].y);
    	
    	for(int i = 1; i < n; ++i) l[i] = Line(t[i], t[i + 1] - t[i]), l[i].ang = atan2(l[i].v.y, l[i].v.x);
    	sort(l + 1, l + n);
    	mkhalf();
    	
    	ans = cal(1);
    	for(int i = 2; i <= n; ++i)
    		ans = min(ans, cal(i));
    	for(int i = head; i < tail; ++i)
    		if (t[1].x <= p[i].x && p[i].x <= t[n].x)
    			ans = min(ans, cal2(i));
    	
    //	for(int i = head; i < tail; ++i) printf("%.2lf %.2lf
    ", p[i].x, p[i].y);
    	
    	printf("%.3lf
    ", ans + 1e-8);
    	return 0;
    }
    

    因为半平面不会围成一个"圈",所以我把最后"去除冗余"的部分注释掉了。最后输出答案加eps是听别人说的,不加会怎么样呢,我也不知道_(:з」∠)_

  • 相关阅读:
    <转>iOS SDK中使用NSXMLParser解析XML
    [原创]闲来无事,写了个c#的数据库附加工具,现附上源代码
    [转载]php数组操作foreach、each、reset、list
    [原创]xml序列化
    [原创]一个简单的药店用的会员积分管理系统
    [原创]我的cms项目
    简洁、标准的对联广告代码
    C#混淆 xenocode使用说明
    .net 随机数
    [原创]c# as用法
  • 原文地址:https://www.cnblogs.com/abclzr/p/5677227.html
Copyright © 2011-2022 走看看