2019牛客暑期多校训练营(第十场)G——Road Construction(思维+计算几何)

链接:https://ac.nowcoder.com/acm/contest/890/G
来源:牛客网
 

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 524288K,其他语言1048576K
Special Judge, 64bit IO Format: %lld

题目描述

The mayor of Byteland is planning to build a new road across the town. Constructing new roads may facilitate transportation and stimulate economic development; the negative aspects include, the noise that may affect the residents nearby, and the nonnegligible impacts on the local ecological environment.

You have been required to draft a road construction plan. In your plan, you can model the residents of the town as points, and the road as a straight line of infinite length. Your plan should satisfy the following conditions:
- The road should not pass through any resident of the city;
- The numbers of residents on both sides of the road are equal;
- The minimum of the distances of the residents to the road is maximized.

The following figure depicts the optimal road construction plan for the first sample test data.

Since there are too many residents in Byteland, you believe it is impossible to find such a construction plan manually. It's your time to write a program and find the optimal plan.

输入描述:

The input starts with a line containing an even integer n (1≤n≤300)(1 \leq n \leq 300)(1≤n≤300) indicating the number of residents in Byteland. It is then followed by n lines, each containing two integers x, y (∣x∣,∣y∣≤106)(|x|, |y| \leq 10^6)(∣x∣,∣y∣≤106), the Cartesian coordinates of a resident. No two residents share the same coordinates.

输出描述:

Print the minimum of the distances of the residents to the road you plan to build. Your answer should have an absolute or relative error of no more than 10−610^{-6}10−6.

示例1

输入

复制

6
0 0
3 0
1 2
4 3
-1 4
5 -3

输出

复制

1.264911064067

示例2

输入

复制

2
1 3
2 5

输出

复制

1.118033988750

题意:找一条线让所有点平均分布在它的两侧,不能再线上,然后求出距离最近的点的最大值;

题解:

1.最优的直线一定平行或垂直于两个点的连线(显然)

2.枚举最优直线斜率(最多有n^2个),然后用kth-element找到以这条直线排序的中间两个点(用截距排序),找到之后求出两条线的距离,答案就是距离/2

上个图看一下:

上代码:

#include <bits/stdc++.h>
using namespace std;
const int MAX = 520;
double x[MAX],y[MAX],b[MAX];
double maxx;
int n;
void solve(double k){
	for (int i = 0; i < n;i++) b[i]=y[i]-k*x[i];//求截距
	nth_element(b,b+n/2,b+n);//找中间右边那个,下面的" *max_element(b,b+n/2) " 是找中间左边那个
	double w=(b[n/2]-*max_element(b,b+n/2))/sqrt(1+k*k);//求距离(右减左,就是大减小)
	maxx=max(maxx,w/2);//均分保证最大
}
int main(){
	scanf("%d",&n);
	for (int i = 0; i < n;i++) scanf("%lf%lf",&x[i],&y[i]);
	for (int i = 0; i < n;i++){
		for (int j = i+1; j < n;j++){
			double k = (y[i]-y[j])/(x[i]-x[j]);
			solve(k);//平行
			solve(-1.0/k);//垂直
		}
	}
	printf("%.12f\n",maxx);
	return 0;
} 
发布了195 篇原创文章 · 获赞 27 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/lgz0921/article/details/99762152
今日推荐