Trash Removal uva1111/uvalive5138 World Final 2011 K 计算几何

题目https://cn.vjudge.net/problem/UVA-1111

题意:扔垃圾,垃圾的形状是(凹凸)多边形,给出多边形的顶点坐标,求最小的垃圾桶宽度,使垃圾能够进入(垃圾可以旋转)。保证输入线段不相交,无重复点。输出精确到小数点后两位。

思路:观察题目给出的例图,可以发现当多边形轮廓(即凸包)上的边紧贴垃圾桶壁时肯定比所有边都不与桶壁平行要好。在此基础上,只要离这条边距离最远的点能通过垃圾桶,那整个多边形就能通过。
那么做法就出来了,对给出的点求凸包,枚举凸包上的边,求其余各点到这条边的最远距离,这些距离中最小的即为答案。
另外有个小细节,既然需要让多边形通过,精确小数时不是四舍五入,需要向上取整。

代码:c++

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
using namespace std;

const double eps = 1e-8;

int dcmp(double a)
{
    if(fabs(a) < eps)
    {
        return 0;
    }
    return a > 0 ? 1 : -1;
}

struct Point
{
    double x, y;
    Point(double xx = 0, double yy = 0): x(xx), y(yy) {}
    bool operator < (const Point &t) const
    {
        return make_pair(x, y) < make_pair(t.x, t.y);
    }
    void show()
    {
        printf("(%g, %g)\n", x, y);
    }
};

typedef Point Vector;

Vector operator - (Point A, Point B)
{
    return Vector(A.x - B.x, A.y - B.y);
}

Vector operator * (Vector A, double p)
{
    return Vector(A.x * p, A.x * p);
}

bool operator == (const Point &A, const Point &B)
{
    return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0;
}

double Dot(Vector A, Vector B)
{
    return A.x * B.x + A.y * B.y;
}

double Length(Vector v)
{
    return sqrt(Dot(v, v));
}

double Cross(Vector A, Vector B)
{
    return A.x * B.y - A.y * B.x;
}

double DistanceToLine(Point p, Point A, Point B)
{
    Vector v1 = B - A;
    Vector v2 = p - A;
    return fabs(Cross(v1, v2)) / Length(v1);
}

void ConvexHull(vector<Point> &p, vector<Point> &hull)
{
    sort(p.begin(), p.end());
    for(int i = 0; i < p.size(); i++)
    {
        while(hull.size() > 1 && Cross(hull.back() - hull[hull.size() - 2], p[i] - hull[hull.size() - 2]) <= 0)
        {
            hull.pop_back();
        }
        hull.push_back(p[i]);
    }
    int k = hull.size();
    for(int i = p.size() - 2; i >= 0; i--)
    {
        while(hull.size() > k && Cross(hull.back() - hull[hull.size() - 2], p[i] - hull[hull.size() - 2]) <= 0)
        {
            hull.pop_back();
        }
        hull.push_back(p[i]);
    }
    if(!hull.empty())
    {
        hull.pop_back();
    }
}

vector<Point> p;
vector<Point> hull;

double LongestDistance(int p1, int p2)
{
    double maxx = 0;
    for(int i = 0; i < hull.size(); i++)
    {
        if(i == p1 || i == p2)
        {
            continue;
        }
        maxx = max(maxx, DistanceToLine(hull[i], hull[p1], hull[p2]));
    }
    return maxx;
}

int main()
{
    int n;
    int cases = 1;
    while(scanf("%d", &n) != EOF && n)
    {
        p.clear();
        hull.clear();
        for(int i = 0; i < n; i++)
        {
            double x, y;
            scanf("%lf%lf", &x, &y);
            p.push_back(Point(x, y));
        }
        ConvexHull(p, hull);
        double minn = LongestDistance(0, hull.size() - 1);
        for(int i = 0; i < hull.size() - 1; i++)
        {
            minn = min(minn, LongestDistance(i, i + 1));
        }
        printf("Case %d: %.2f\n", cases++, 0.01 * ceil(minn * 100));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Rewriter_huanying/article/details/78466431