[ZJOI2008]瞭望塔

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;
} 

原文地址:https://www.cnblogs.com/Troverld/p/14619311.html