BZOJ 1038 ZJOI2008 瞭望塔 半平面交

来源:互联网 发布:天干地支最简单的算法 编辑:程序博客网 时间:2024/05/21 11:01

题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759 

这次用半平面交写了一遍……求出半平面交之后,枚举原图和半平面交的每个点,求出答案即可

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 310#define eps 1e-7using namespace std;struct point{double x,y;}points[M];struct line{point *p1,*p2;double k,b;void Get_Parameters(){k=(double)(p1->y-p2->y)/(p1->x-p2->x);b=p1->y-k*p1->x;}bool operator < (const line &x) const{if( fabs(k-x.k)<eps )return b < x.b;return k < x.k;}}lines[M];int n;double ans=1e11;line *stack[M];int top;inline point Get_Intersection(const line &l1,const line &l2){point re;re.x=-(l1.b-l2.b)/(l1.k-l2.k);re.y=l1.k*re.x+l1.b;return re;}void Insert(line &l){while(top>=2){if( Get_Intersection(*stack[top],l).x < Get_Intersection(*stack[top-1],*stack[top]).x )--top;elsebreak;}stack[++top]=&l;}double F(double x){int i;double re=0;for(i=1;i<=top;i++)re=max(re,stack[i]->k*x+stack[i]->b);return re;}double G(double x){int i;for(i=n;i;i--)if(x>=points[i].x)break;return points[i].y+(x-points[i].x)/(points[i+1].x-points[i].x)*(points[i+1].y-points[i].y);}int main(){int i;cin>>n;for(i=1;i<=n;i++)scanf("%lf",&points[i].x);for(i=1;i<=n;i++)scanf("%lf",&points[i].y);for(i=1;i<n;i++)lines[i].p1=points+i,lines[i].p2=points+i+1,lines[i].Get_Parameters();sort(lines+1,lines+n);for(i=1;i<n;i++)if(i==n-1||fabs(lines[i].k-lines[i+1].k)>eps)Insert(lines[i]);for(i=1;i<=n;i++)ans=min(ans,F(points[i].x)-points[i].y);for(i=1;i<top;i++){point p=Get_Intersection(*stack[i],*stack[i+1]);ans=min(ans,p.y-G(p.x));}printf("%.3lf\n",ans);}



0 0