首页 > 代码库 > UVA 12386 Smallest Polygon n个点的任意多边形求最小周长 科学的暴力
UVA 12386 Smallest Polygon n个点的任意多边形求最小周长 科学的暴力
题目链接:
题意:
给定n个点,用n个点组成的多边形中(可以是凹多边形,但n个点一定要全在多边形上)
在所有能由n个点构成的多边形中
求最小面积的多边形的周长 - 最小周长。
思路:
首先我们选择一个定点,则接下来的数进行一个排列,有(n-1)!个排列。
这个序列相邻两个数之间有一条线段。
判断多边形合法:任意两条线段不相交即可。n^2
剩下就是简单的更新答案了。
所以复杂度是 ( n-1 ) ! * n*n
#include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <cmath> using namespace std; const int MAX_N = 2507; struct point { double x, y; point(double _x = 0, double _y = 0) { x = _x, y = _y; } bool operator < (const point &rhs) const { if (x != rhs.x) return x < rhs.x; return y < rhs.y; } }; int n; int top; point st[100], p[100]; typedef point Point; double cross(point p0, point p1, point p2) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } double mult_cross(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x); } bool is_cross(Point p1, Point p2, Point p3, Point p4) { if (std::min(p1.x, p2.x) <= std::max(p3.x, p4.x) && std::min(p3.x, p4.x) <= std::max(p1.x, p2.x) && std::min(p1.y, p2.y) <= std::max(p3.y, p4.y) && std::min(p3.y, p4.y) <= std::max(p1.y, p2.y) && mult_cross(p1, p4, p3) * mult_cross(p2, p4, p3) <= 0 && mult_cross(p3, p2, p1) * mult_cross(p4, p2, p1) <= 0) return true; return false; } double dis(point p1, point p2) { return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); } int b[100]; bool check() { b[n - 1] = n - 1; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (i == j) continue; int x = (i + 1) % n, y = (j + 1) % n; if (i == y || j == x || x == y) continue; if (is_cross(p[b[i]], p[b[x]], p[b[j]], p[b[y]])) return false; } } return true; } inline double Cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; } bool Equal(double a, double b) { return fabs(a - b) < 1e-6; } int main() { int T; scanf("%d", &T); while (T-- > 0) { scanf("%d", &n); for (int i = 0; i < n; ++i) { int x, y; scanf("%d%d", &x, &y); p[i].x = 1. * x, p[i].y = 1. * y; } if (n == 3) { puts("0.0000"); continue; } for (int i = 0; i < n - 1; ++i) b[i] = i; double minlength = -1, minarea = -1, minarealength = -1; do { if (check()) { double area = 0, length = 0; b[n] = b[0]; for (int i = 0; i < n; i++) { length += dis(p[b[i]], p[b[i+1]]); area += Cross(p[b[i]], p[b[i+1]]); } area = fabs(area) * 0.5; // printf("www %.4f %.4f\n", area, length); // for (int i = 0; i < n; ++i) printf("(%d %.f %.f) ", b[i], p[b[i]].x, p[b[i]].y); puts(""); if (minlength == -1) { minlength = length; minarea = area; minarealength = length; } else { minlength = min(minlength, length); if (minarea > area || (Equal(area, minarea) && length < minarealength)) { minarea = area; minarealength = length; } } } // for (int i = 0; i < n; ++i) printf("%d ", b[i]); } while (next_permutation(b, b + n - 1)); // printf("%.4f %.4f %.4f\n", minlength, minarealength, minarea); printf("%.4f\n", fabs(minarealength - minlength)); } return 0; }
UVA 12386 Smallest Polygon n个点的任意多边形求最小周长 科学的暴力
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。