版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88943135
题目
对于每个坡,能看到它的范围为一个半平面,做半平面交得到一个下凸壳。
发现答案一定在下凸壳的顶点或折线的顶点处取。
AC Code:
#include<bits/stdc++.h>
#define maxn 1005
#define eps 1e-8
using namespace std;
int n;
struct Point{
double x,y;
Point (double x=0,double y=0):x(x),y(y){}
Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
Point operator +(const Point &B)const{ return Point(x+B.x,y+B.y); }
double operator *(const Point &B)const{ return x*B.y-y*B.x; }
Point operator *(const double &B)const{ return Point(x*B,y*B); }
}P[maxn];
struct Line{
Point A,B;
double ag;
}L[maxn];
int id[maxn],tot,qL[maxn],l,r;
Point qp[maxn];
inline int sgn(double a){ return a<-eps?-1:a>eps?1:0; }
inline bool inLeft(const Point &P,const Point &A,const Point &B){
return sgn((B-A)*(P-A))==1;
}
inline bool onLeft(const Point &P,const Point &A,const Point &B){
return sgn((B-A)*(P-A))>=0;
}
inline bool cmp(const int &u,const int &v){
if(sgn(L[u].ag-L[v].ag)) return L[u].ag<L[v].ag;
return inLeft(L[u].A,L[v].A,L[v].B);
}
Point Ipt(const Point &p1,const Point &p2,const Point &p3,const Point &p4){
Point u=p2-p1,v=p4-p3,w=p2-p4;
return p2+(p1-p2)*((w*v)/(u*v));
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf",&P[i].x);
for(int i=1;i<=n;i++) scanf("%lf",&P[i].y);
for(int i=1;i<n;i++){
L[++tot].A=P[i],L[tot].B=P[i+1];
L[tot].ag=atan2(P[i+1].y-P[i].y,P[i+1].x-P[i].x);
id[tot]=tot;
}
sort(id+1,id+1+tot,cmp);
qL[r++] = id[1];
for(int i=2,u;i<=tot;i++)
if(sgn(L[u=id[i]].ag-L[id[i-1]].ag)){
for(;r-l>=2 && !onLeft(qp[r-2],L[u].A,L[u].B);r--);
for(;r-l>=2 && !onLeft(qp[l],L[u].A,L[u].B);l++);
qL[r++] = u;
if(r-l>=2)
qp[r-2] = Ipt(L[qL[r-2]].A,L[qL[r-2]].B,L[u].A,L[u].B);
}
for(;r-l>=2 && !onLeft(qp[r-2],L[qL[l]].A,L[qL[l]].B);r--);
int k = l;
double ans = 2e17;
for(int i=1;i<=n;i++){
for(;k<=r-2 && qp[k].x<P[i].x;k++);
ans = min(ans , max(0.0,Ipt(Point(P[i].x,0),Point(P[i].x,1),L[qL[k]].A,L[qL[k]].B).y - P[i].y));
}
k = 2;
for(int i=l;i<=r-2;i++){
for(;k<=n && P[k].x <= qp[i].x;k++);
if(k<=n)
ans = min(ans , max(0.0,qp[i].y-Ipt(Point(qp[i].x,0),Point(qp[i].x,1),P[k-1],P[k]).y));
else
break;
}
printf("%.3lf\n",ans);
}