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

来源:互联网 发布:淘宝客服外包 编辑:程序博客网 时间:2024/05/17 15:17

题目链接

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-6using 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;}
0 0
原创粉丝点击