Codeforces 800B 计算几何

版权声明:欢迎转载,不要求署名~~~ https://blog.csdn.net/shadandeajian/article/details/82078405

传送门:题目

题意:

n个点,按照输入的顺序,顺时针连接每个点,可以组成一个凸的多边形,我们可以移动任意一个点,在以该点为圆心,半径不超过d的范围内,假设,移动后的多边形,保证任意两条边不是相交的,以及它依然是一个凸形,d最大为多少?

题解:

明显是一道计算几何的题,我们只需要考虑如何满足上面两个条件即可:

  • 保证任意两条边不相交,相邻点的距离小于 2 d 即可
  • 我们知道,未改变之前它是一个凸的,我们只要保证任意一个点,到相邻两点连成的线的距离小于 2 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;
}

猜你喜欢

转载自blog.csdn.net/shadandeajian/article/details/82078405