P1663 山

Posted mysh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1663 山相关的知识,希望对你有一定的参考价值。

题目描述

给出一座山,如图。

技术图片

现在要在山上的某个部位装一盏灯,使得这座山的任何一个部位都能够被看到。

给出最小的y坐标,如图的+号处就是y坐标最小的安装灯的地方。

输入格式

第一行一个数N,表示这座山由N个点构成;

接下来N行从左到右给出了这座山的构造情况,每行两个数Xi、Yi,表示一个折点,保证Xi>Xi-1

输出格式

仅输出一行,为最小的y坐标,当你的答案与标准答案相差不超过0.01时,则被认为是正确的。

输入输出样例

输入 #1
6
0 0
10 0
11 1
15 1
16 0
25 0
输出 #1
3.00

说明/提示

数据规模:

30%的数据,1≤N≤50;

100%的数据,1≤N≤5000;0≤Xi,Yi≤100000,保证答案不超过1000000.

思路

如果我们把相邻的两个点连接起来,看作一条条直线,那么我们可以发现我们要求的就是找到一个点,使它在每一条的直线的上方或在直线上,并且要求y坐标越小越好。

首先第一步当然是这n-1条直线的表达式给求出来(见初二上册数学课本)

然后我们会发现,对于我们枚举的每一个高度,对于每一条直线都有一个满足要求的区间,那么我们怎么判断这个高度是否可行?显然,若这些区间有交集的话,那么就是有解了,否则就是不行。

枚举高度我们可以通过二分来实现,剩下就是解一下不等式问题就可以了。

代码

 

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=5010;

int n;
double l,r,mid;
double ll,rr,ans;

struct no 
	int x,y;
 a[N];

struct nod 
	double k,b;
 b[N];

bool check(double x) 
	ll=-2e9,rr=2e9;
	for(int i=1; i<n; i++) 
		if(b[i].k<0)
			ll=max(ll,(x-b[i].b)/b[i].k);
		if(b[i].k>0)
			rr=min(rr,(x-b[i].b)/b[i].k);
		if (b[i].k==0&&b[i].b>x)
			return 0;
	
	return ll<=rr;


int main () 
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
		scanf("%d%d",&a[i].x,&a[i].y);
	for(int i=1; i<n; i++) 
		b[i].k=1.0*(a[i].y-a[i+1].y)/(a[i].x-a[i+1].x);
		b[i].b=1.0*a[i].y-b[i].k*a[i].x;
	
	l=0,r=1000000;
	ans=-1;
	while(r-l>=0.001) 
		mid=(l+r)/2;
		if(check(mid)) 
			ans=mid;
			r=mid;
		 else
			l=mid;
	
	printf("%.2lf\n",ans);
	return 0;

 

 

 

以上是关于P1663 山的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P1663 山二分答案/实数域By cellur925

看山不是山,看水不是水

C++不知算法系列之迷宫问题中的“见山不是山”

常无与常有

前端为何要组件化——看山还是山

2017Final 圆周率山