c_cpp uva12307

Posted

tags:

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

#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
#include <tuple>
#include <vector>
using namespace std;

template <typename T>
class _point
{
public:
    _point() : x(), y()
    {
    }

    _point(const T& x, const T& y) : x(x), y(y)
    {
    }

    _point operator -(const _point& p) const
    {
        return _point(x - p.x, y - p.y);
    }

    bool operator ==(const _point& p) const
    {
        return (x == p.x) && (y == p.y);
    }

    bool operator !=(const _point& p) const
    {
        return !(*this == p);
    }

    bool operator <(const _point& p) const
    {
        return (x != p.x) ? (x < p.x) : (y < p.y);
    }

    double length() const
    {
        return sqrt(x*x + y*y);
    }

    T dot(const _point& p) const
    {
        return x*p.x + y*p.y;
    }

    T cross(const _point& p) const
    {
        return x*p.y - y*p.x;
    }

    static T cross(const _point& o, const _point& a, const _point& b)
    {
        return (a - o).cross(b - o);
    }

private:
    friend istream& operator >>(istream& is, _point& p)
    {
        is >> p.x >> p.y;
        return is;
    }

    friend ostream& operator <<(ostream& os, const _point& p)
    {
        os << p.x << " " << p.y;
        return os;
    }

private:
    T x, y;
};

using point = _point<double>;

vector<point> find_convex_hull(vector<point> points)
{
    if (points.size() <= 2)
    {
        if (points.front() != points.back()) points.push_back(points.front());
        return points;
    }

    sort(points.begin(), points.end());

    auto back = [](const vector<point>& container, size_t offset)
    {
        return *(container.rbegin() + offset);
    };

    vector<point> convex;

    for (auto it = points.cbegin(); it != points.cend(); it++)
    {
        while (convex.size() > 1 && point::cross(back(convex, 1), back(convex, 0), *it) <= 0) convex.pop_back();
        convex.push_back(*it);
    }

    size_t s = convex.size();
    for (auto it = points.rbegin(); it != points.rend(); it++)
    {
        while (convex.size() > s && point::cross(back(convex, 1), back(convex, 0), *it) <= 0) convex.pop_back();
        convex.push_back(*it);
    }

    return convex;
}

tuple<double, double> find_smallest_enclosing_rect(const vector<point>& points)
{
    const auto convex = find_convex_hull(points); // The first point has been duplicated at the end.

    if (convex.size() <= 2 + 1) return { 0, 0 };

    constexpr auto MAX_VALUE = numeric_limits<double>::max();
    auto min_area = MAX_VALUE, min_perimeter = MAX_VALUE;

    size_t size = convex.size() - 1;
    size_t r = 1, l = 1, t = 1;

    for (size_t i = 0; i < size; i++)
    {
        auto origin = convex[i];
        auto o2p = [&convex, size, origin](size_t index)
        {
            return convex[index%size] - origin;
        };
        auto edge = o2p(i + 1);
        auto edge_len = edge.length();

        while (r < 0 || edge.dot(o2p(r)) < edge.dot(o2p(r + 1))) r++;
        while (t < r || edge.cross(o2p(t)) < edge.cross(o2p(t + 1))) t++;
        while (l < t || edge.dot(o2p(l)) > edge.dot(o2p(l + 1))) l++;

        double width = (edge.dot(o2p(r)) - edge.dot(o2p(l))) / edge_len;
        double height = edge.cross(o2p(t)) / edge_len;

        min_area = min(min_area, width*height);
        min_perimeter = min(min_perimeter, (width + height)*2.0);
    }

    return { min_area, min_perimeter };
}

bool test_case()
{
    size_t n;
    cin >> n;
    if (n == 0) return false;

    vector<point> points(n);
    for (auto& p : points) cin >> p;

    double area, perimeter;
    tie(area, perimeter) = find_smallest_enclosing_rect(points);

    cout << fixed << setprecision(2) << area << " " << perimeter << endl;
    return true;
}

int main()
{
    while (test_case());
    return 0;
}

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

c_cpp uva10189

c_cpp uva10093

c_cpp uva681

c_cpp uva10101

c_cpp uva10107

c_cpp uva591