[省选前题目整理][BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)

题目链接

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

思路

http://blog.csdn.net/qpswwww/article/details/44105605
这个半平面交并不可以当作模板用,因为这里的半平面交并不是一个封闭的多边形,因此少了很多一般的半平面交的细节

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>

#define MAXN 1000
#define EPS 1e-6

using namespace std;

struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y):x(_x),y(_y){}
}points[MAXN];

struct Line
{
    Point s,t;
    double k,b,ang;
    Line(){}
    Line(Point _s,Point _t):s(_s),t(_t)
    {
        k=(s.y-t.y)/(s.x-t.x);
        b=s.y-k*s.x;
        ang=atan2(t.y-s.y,t.x-s.x);
    }
}lines[MAXN],stack[MAXN];

bool cmp(Line a,Line b)
{
    if(fabs(a.ang-b.ang)<EPS) return a.b<b.b;
    return a.ang<b.ang;
}

int top=0;

Point operator-(Point a,Point b)
{
    return Point(a.x-b.x,a.y-b.y);
}

double cross(Point a,Point b)
{
    return a.x*b.y-a.y*b.x;
}

Point getLineIntersec(Line x,Line y)
{
    Point o;
    o.x=(x.b-y.b)/(y.k-x.k);
    o.y=x.k*o.x+x.b;
    return o;
}

void HalfPanelIntersec(int n)
{
    sort(lines+1,lines+n+1,cmp);
    top=0;
    for(int i=1;i<=n;i++)
        if(i==n||fabs(lines[i].k-lines[i+1].k)>EPS)
        {
            while(top>=2&&getLineIntersec(lines[i],stack[top]).x<getLineIntersec(stack[top-1],stack[top]).x) top--;
            stack[++top]=lines[i];
        }
}

double calc1(double x)
{
    double maxh=0;
    for(int i=1;i<=top;i++)
        maxh=max(maxh,stack[i].k*x+stack[i].b);
    return maxh;
}

double calc2(int n,double x)
{
    for(int i=2;i<=n;i++)
    {
        if(points[i].x>=x)
            return points[i].y-(points[i].y-points[i-1].y)*(points[i].x-x)/(points[i].x-points[i-1].x);
    }
    return 0;
}

int main()
{
    int n;
    double ans=1e12;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lf",&points[i].x);
    for(int i=1;i<=n;i++)
        scanf("%lf",&points[i].y);
    for(int i=1;i<n;i++)
        lines[i]=Line(points[i],points[i+1]);
    HalfPanelIntersec(n-1);
    for(int i=1;i<=n;i++)
        ans=min(ans,calc1(points[i].x)-points[i].y); //!!!!!
    for(int i=1;i<top;i++)
    {
        Point tmp=getLineIntersec(stack[i],stack[i+1]); //!!!!
        ans=min(ans,tmp.y-calc2(n,tmp.x));
    }
    printf("%.3lf\n",ans);
    return 0;
}

你可能感兴趣的:([省选前题目整理][BZOJ 1038][ZJOI 2008]瞭望塔(半平面交))