luogu P2600 [ZJOI2008]瞭望塔
大意
题目讲得很清楚啊
题解
可以发现,那个点一定是某两条直线的交点
然后直接枚举两条直线就好了
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
double x[305], y[305];
struct A{
double k, b;
}l[305];
int n;
double calc(double xx){//计算能看见所有点的最小的y
double ans = 0;
for(int i = 1; i < n; i ++) ans = max(ans, l[i].k * xx + l[i].b);
return ans;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%lf", &x[i]);
for(int i = 1; i <= n; i ++) scanf("%lf", &y[i]);
for(int i = 1; i < n; i ++)
l[i].k = (y[i] - y[i + 1]) / (x[i] - x[i + 1]), l[i].b = y[i] - l[i].k * x[i];//处理出每条直线
double ans = 999999999999;
for(int i = 1; i <= n; i ++)
ans = min(ans, calc(x[i]) - y[i]);//先看放在节点上的
for(int i = 1; i < n; i ++)
for(int j = i + 1; j < n; j ++){
double xx = (l[j].b - l[i].b) / (l[i].k - l[j].k);//两直线交点的x
for(int k = 1; k < n; k ++)
if(x[k] <= xx && xx <= x[k + 1]) ans = min(ans, calc(xx) - l[k].k * xx - l[k].b);//计算瞭望塔的高度
}
printf("%.3f", ans);
return 0;
}
坑点
注意节点上的也要考虑