卧薪尝胆,厚积薄发。
ZJOI2008 瞭望塔
Date: Sun Dec 09 09:30:59 CST 2018 In Category: NoCategory

Description:

给一个轮廓线,要求建一个瞭望塔能看到轮廓线的所有位置,问塔的最小高度是多少。
$1\leqslant n\leqslant 300$

Solution:

轮廓线每一条线都可以看成一个半平面,可以把它们拿出来做半平面交,然后可以发现最优解一定在原来轮廓线的拐弯处或者半平面交的拐弯处,所以把这些点拿出来计算就行了,这道题由于数据规模小所以并不用真的半平面交。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;
int n;
#define MAXN 310
struct point
{
double x,y;
}p[MAXN];
bool cmp_x(point a,point b){return a.x < b.x;}
struct line
{
double k,b;
}l[MAXN];
double calc(double x1,double y1,double x2,double y2,double x)
{
double slope = (y2 - y1) / (x2 - x1);
return x * slope + y1 - x1 * slope;
}
double fabs(double k){return (k < 0 ? -k : k);}
bool equal(double a,double b){return fabs(a - b) <= 1e-8;}
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);
sort(p + 1,p + 1 + n,cmp_x);
for(int i = 1;i < n;++i)
{
l[i].k = (p[i + 1].y - p[i].y) / (p[i + 1].x - p[i].x);
l[i].b = p[i].y - l[i].k * p[i].x;
}
double ans = 1000000000000;
for(int i = 1;i < n;++i)
{
for(int j = 1;j < n;++j)
{
if(equal(l[i].k,l[j].k))continue;
double x = (l[i].b - l[j].b) / (l[j].k - l[i].k);
if(x < p[1].x || x > p[n].x)continue;
double top = x * l[i].k + l[i].b;
int s;
for(s = 1;s < n;++s)
{
if(p[s].x <= x && x <= p[s + 1].x)break;
}
for(int w = 1;w < n;++w)
{
top = max(top,calc(p[w].x,p[w].y,p[w + 1].x,p[w + 1].y,x));
}
double bot = calc(p[s].x,p[s].y,p[s + 1].x,p[s + 1].y,x);
ans = min(ans,top - bot);
}
}
printf("%.3lf\n",ans);
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡