IX.[ZJOI2008]瞭望塔
ZJOI2008咋总喜欢考这种计算几何的题啊……
同我们的IV.监视摄像机[CTSC1998]一样,本题相当于求多边形的核,可以使用半平面交。但因为和VI.[HNOI2008]水平可见直线一样,所有半平面都是向上的,故直接求凸包即可。
发现求完凸包后,答案的横坐标一定是凸包上点的横坐标/题目中给出的横坐标,故直接双针扫一遍即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int X[310],Y[310],stk[310],tp;
pair<double,double>p[310],q[310];
double res=0x3f3f3f3f3f3f3f3f;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&X[i]);
for(int i=1;i<=n;i++)scanf("%d",&Y[i]);
for(int i=1;i<n;i++)q[i]=p[i]=make_pair(1.0*(Y[i+1]-Y[i])/(X[i+1]-X[i]),1.0*(1ll*Y[i+1]*(X[i+1]-X[i])-1ll*X[i+1]*(Y[i+1]-Y[i]))/(X[i+1]-X[i]));
// for(int i=1;i<n;i++)printf("%lf %lf\n",p[i].first,p[i].second);
sort(p+1,p+n),stk[++tp]=1;
for(int i=2;i<n;i++){
if(fabs(p[i].first-p[i-1].first)<1e-6){stk[tp]=i;continue;}
while(tp>=2&&(p[i].second-p[stk[tp]].second)/(p[i].first-p[stk[tp]].first)>=(p[stk[tp]].second-p[stk[tp-1]].second)/(p[stk[tp]].first-p[stk[tp-1]].first))tp--;
stk[++tp]=i;
}
for(int i=1,j=1;i<=n;i++){
while(j<tp&&(p[stk[j+1]].second-p[stk[j]].second)/(p[stk[j]].first-p[stk[j+1]].first)<=X[i]){
if(i>1){
double x=(p[stk[j+1]].second-p[stk[j]].second)/(p[stk[j]].first-p[stk[j+1]].first),y=x*p[stk[j]].first+p[stk[j]].second;
double yy=x*q[i-1].first+q[i-1].second;
res=min(res,y-yy);
}
j++;
}
double y=X[i]*p[stk[j]].first+p[stk[j]].second;
res=min(res,y-Y[i]);
}
printf("%.3lf\n",res);
return 0;
}