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的主要内容,如果未能解决你的问题,请参考以下文章