版权声明:欢迎转载,不要求署名~~~ https://blog.csdn.net/shadandeajian/article/details/82078405
传送门:题目
题意:
给n个点,按照输入的顺序,顺时针连接每个点,可以组成一个凸的多边形,我们可以移动任意一个点,在以该点为圆心,半径不超过d的范围内,假设,移动后的多边形,保证任意两条边不是相交的,以及它依然是一个凸形,d最大为多少?
题解:
明显是一道计算几何的题,我们只需要考虑如何满足上面两个条件即可:
- 保证任意两条边不相交,相邻点的距离小于 即可
- 我们知道,未改变之前它是一个凸的,我们只要保证任意一个点,到相邻两点连成的线的距离小于 即可保证,这个点穿不过这条线,故,能保证它不能改变自身的凹凸性。
- 让我们求d的最大值,二分答案即可。
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iomanip>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1010;
/**********************计算几何----点线距离模板***********/
struct Point//double
{
double x, y;
Point(double x = 0, double y = 0): x(x), y(y) {}
void show(){
printf("(%.5lf,%.5lf)\n", x, y);
}
} point[maxn];
Point operator+(Point A, Point B) {return (Point) {A.x + B.x, A.y + B.y};} //向量A+B
Point operator-(Point A, Point B) {return (Point) {A.x - B.x, A.y - B.y};} //向量A-B
Point operator*(Point A, double B) {return (Point) {A.x*B, A.y*B};} //向量A*B
Point operator/(Point A, double B) {return (Point) {A.x / B, A.y / B};} //向量A/B
double operator*(Point A, Point B) {return A.x * B.x + A.y * B.y;} //向量A B的点积
double operator^(Point A, Point B) {return A.x * B.y - A.y * B.x;} //向量A B的叉积
double cross(Point A, Point B) {return A.x * B.y - A.y * B.x;} //向量A B的叉积
double dis(Point A, Point B) {return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));} //A B两点的距离
int operator==(const Point&A, const Point&B) {return A.x == B.x && A.y == B.y;} //判断A B两点是否相等
double Distoline(Point P, Point A, Point B) {return fabs(cross(B - A, P - A)) / dis(A, B);}//点P到直线AB距离
/**********************计算几何----点线距离模板***********/
bool solve(double x, int n) {
for (int i = 0; i < n; i++)
if (dis(point[i], point[(i + 1) % n]) <= 2 * x || Distoline(point[i], point[(i - 1 + n) % n], point[(i + 1) % n]) <= 2 * x)
return true;
return false;
}
int main(void) {
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> point[i].x >> point[i].y;
double l = 0, r = 1e18, ans;
int T = 100;
while (T--) {
double m = (l + r) / 2;
if (solve(m, n))
r = m;
else
ans = l = m;
}
cout << fixed << setprecision(10) << ans << endl;
return 0;
}