luogu P2600 [ZJOI2008]瞭望塔

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

坑点

注意节点上的也要考虑

posted @ 2019-08-13 20:30  lahlah  阅读(15)  评论(0编辑  收藏  举报