zoukankan      html  css  js  c++  java
  • P2600 [ZJOI2008]瞭望塔

    题目描述

    致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安。

    我们将H村抽象为一维的轮廓。如下图所示

    img

    我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长希望建造的塔高度尽可能小。

    请你写一个程序,帮助dadzhi村长计算塔的最小高度。

    输入格式

    输入文件tower.in第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1 ~ yn。

    输出格式

    输出文件tower.out仅包含一个实数,为塔的最小高度,精确到小数点后三位。

    输入输出样例

    输入 #1

    6
    
    1 2 4 5 6 7
    
    1 2 2 4 2 1
    

    输出 #1

    1.000
    

    说明/提示

    对于60%的数据, N ≤ 60;

    对于100%的数据, N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。

    半平面交练习题 , 注意判断有没有在右边时 , 想清楚在线上的要不要

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int N = 350;
    const double eps = 1e-7;
    int n , head , tail;
    struct point{
    	double x , y;
    	point(double X = 0.0 , double Y = 0.0): x(X) , y(Y) {}
    	bool operator < (const point &A) const { return x < A.x; }
    	friend point operator - (point A , point B) { return point(A.x - B.x , A.y - B.y); }
    	friend point operator * (point A , double B) {return point(A.x * B , A.y * B); }
    	friend point operator + (point A , point B) { return point(A.x + B.x , A.y + B.y); }
    } a[N] , p[N];
    
    struct Line{
    	point v , p;
    	double an;
    	Line(point V = point(0,0), point P = point(0,0)) : v(V) , p(P) { an = 0.0;}
    	bool operator < (const Line A) const { return an < A.an; }
    } l[N] , sta[N] , li[N];
    inline int dcmp(double A) { return fabs(A) < eps ? 0 : (A < eps ? -1 : 1); }
    inline double accross(point A , point B) { return A.x * B.y - A.y * B.x; }
    inline bool onright(point A , Line B) { return dcmp(accross(A - B.p , B.v)) > 0; }
    inline point meetline(Line A , Line B)
    {
    	if(dcmp(accross(A.v , B.v)) == 0) return (point){0 , 0};
    	point k = A.p - B.p;
    	return A.p + A.v * (accross(B.v , k) / accross(A.v , B.v));
    }
    
    int Get_ans(int n)
    {
    	sort(l + 1 , l + 1 + n); sta[head = tail = 1] = l[1];
    	for(int i = 2 ; i <= n ; ++i)
    	{
    		while(head < tail && onright(p[tail-1] , l[i])) tail--;
    		while(head < tail && onright(p[head] , l[i])) head++;
    		sta[++tail] = l[i];
    		if(dcmp(accross(sta[tail].v , sta[tail-1].v)) == 0)
    		{
    			tail--;
    			if(onright(sta[tail].p , l[i])) sta[tail] = l[i];
    		}
    		if(head < tail) p[tail-1] = meetline(sta[tail] , sta[tail-1]);
    	}
    	while(head < tail && onright(p[tail-1] , sta[head])) tail--;
    	for(int i = head ; i <= tail ; ++i) p[i-head+1] = p[i] , sta[i-head+1] = sta[i]; 
    	return tail - head;
    }
    
    double calc(point p , point a , point b)
    {
    	double K = (b.y - a.y) / (b.x - a.x);
    	double B = a.y - K * a.x;
    	return fabs(p.x * K + B - p.y);
    }
    
    int main()
    {
    	scanf("%d" , &n);
    	for(int i = 1 ; i <= n ; ++i) scanf("%lf" , &a[i].x);
    	for(int i = 1 ; i <= n ; ++i) scanf("%lf" , &a[i].y);
    	sort(a + 1 , a + 1 + n);
    	for(int i = 1 ; i < n ; ++i) l[i].v = a[i+1] - a[i] , l[i].p = a[i] , l[i].an = atan2(l[i].v.y , l[i].v.x) , li[i] = l[i];
    	int cnt = Get_ans(n - 1);
    	// cout << cnt << endl;
    	int l = 1 , r = 1; double ans = 1e15;
    	while(l <= cnt && r <= n)
    	{
    		if(p[l].x < a[r].x)
    		ans = min(ans , p[l].y - meetline(li[r-1] , Line(point(0,1) , p[l])).y) , l++;
    		else
    		ans = min(ans , meetline(sta[l] , Line(point(0,1) , a[r])).y - a[r].y) , r++;
    	}
    	while(l <= cnt) ans = min(ans , p[l].y - meetline(li[r-1] , Line(point(0,1) , p[l])).y) , l++;
    	while(r <=  n)  ans = min(ans , meetline(sta[l] , Line(point(0,1) , a[r])).y - a[r].y) , r++;
    	printf("%.3f" , ans);
    	return 0;
    }
    /*
    4
    10 20 49 59
    0 10 10 0
    */
    
  • 相关阅读:
    hdu 4947
    hdu 4946
    hdu 4944
    hdu 4942
    hdu 4941
    PAT 【L2-011 玩转二叉树】
    PAT【L2-006 树的遍历】
    XYNUOJ 【2070: 重建二叉树】
    XYNUOJ 【1367: 二叉链表存储的二叉树】
    XYNUOJ 2390【二叉树遍历2】
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12147886.html
Copyright © 2011-2022 走看看