BZOJ 1038 ZJOI2008 瞭望塔 半平面交
题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759
这次用半平面交写了一遍……求出半平面交之后。枚举原图和半平面交的每一个点,求出答案就可以
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 310 #define eps 1e-7 using 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; else break; } 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); }