标签:blog io ar os sp for on 2014 log
题目链接:
题意:
给定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个点的任意多边形求最小周长 科学的暴力
标签:blog io ar os sp for on 2014 log
原文地址:http://blog.csdn.net/qq574857122/article/details/41783029