uva 12307(点集的外接矩形)
来源:互联网 发布:centos 7 锁屏 编辑:程序博客网 时间:2024/05/29 20:01
题意:平面上有n个点,要求求出包含所有点的矩形的最小面积和最小周长。
题解:先求点集的凸包,然后把凸包的每条边当做底边,把其他左、上、右三边根据底边用旋转卡壳的方式确定,计算长宽更新最小值。做了这题后对旋转卡壳理解更深刻了。
#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <algorithm>using namespace std;const double eps = 1e-11;const double PI = acos(-1);int dcmp(double x) { if (fabs(x) < eps) return 0; return x > 0 ? 1 : -1;}struct Point { double x, y; Point (double a = 0, double b = 0): x(a), y(b) {}};typedef Point Vector;typedef vector<Point> Polygon;Vector operator + (const Vector& a, const Vector& b) { return Vector(a.x + b.x, a.y + b.y); }Vector operator - (const Vector& a, const Vector& b) { return Vector(a.x - b.x, a.y - b.y); }Vector operator * (const Vector& a, double& b) { return Vector(a.x * b, a.y * b); }Vector operator / (const Vector& a, double& b) { return Vector(a.x / b, a.y / b); }bool operator == (const Vector& a, const Vector& b) { return !dcmp(a.x - b.x) && !dcmp(a.y - b.y); }bool operator < (const Vector& a, const Vector& b) { return a.x < b.x || (a.x == b.x && a.y < b.y); }double Dot(const Vector& a, const Vector& b) { return a.x * b.x + a.y * b.y; }double Length(const Vector& a) { return sqrt(Dot(a, a)); }double Length2(const Vector& a) { return Dot(a, a); }double Cross(const Vector& a, const Vector& b) { return a.x * b.y - a.y * b.x; }double Angle(const Vector& a, const Vector& b) { return acos(Dot(a, b) / Length(a) / Length(b)); }Vector Rotate(Vector A, double rad) { return Point(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); }int ConvexHull(Point* P, int cnt, Point* res) { sort(P, P + cnt); cnt = unique(P, P + cnt) - P; int m = 0; for (int i = 0; i < cnt; i++) { while (m > 1 && Cross(res[m - 1] - res[m - 2], P[i] - res[m - 2]) <= 0) m--; res[m++] = P[i]; } int k = m; for (int i = cnt - 2; i >= 0; i--) { while (m > k && Cross(res[m - 1] - res[m - 2], P[i] - res[m - 2]) <= 0) m--; res[m++] = P[i]; } if (cnt > 1) m--; return m;}void GetMinRCarea(Point* P, int cnt, double& S, double& C) { S = C = 1e18; int l = 1, r = 1, u = 1; for (int i = 0; i < cnt; i++) { //枚举底边P[i]~P[i+1] while (Cross(P[i + 1] - P[i], P[u + 1] - P[u]) > eps) u = (u + 1) % cnt;//找上边,夹角还能增加就向后找 while (Dot(P[i + 1] - P[i], P[r + 1] - P[r]) > eps) r = (r + 1) % cnt;//找右边,夹角还小于90°就继续找 if (i == 0) l = (r + 1) % cnt; while (Dot(P[i + 1] - P[i], P[l + 1] - P[l]) < -eps) l = (l + 1) % cnt;//找左边,夹角还大于90°就继续找 double d = Length(P[i + 1] - P[i]); //底边长度 double a = Cross(P[i + 1] - P[i], P[u] - P[i]) / d;//叉积几何意义就是求向量组成的平行四边形面积,除以底边就是高 double b = (Dot(P[r] - P[i], P[i + 1] - P[i]) - Dot(P[l] - P[i], P[i + 1] - P[i])) / d;//向左向右的投影和(点积几何意义:A*B = |A||B|cosθ一个向量在另一个向量方向上的投影长度乘后者的长度),所以最后还要除后者的长度。 S = min(S, a * b); C = min(C, 2.0 * (a + b)); }}const int N = 100005;Point P[N], R[N];int n;int main() { while(scanf("%d", &n) == 1 && n) { for (int i = 0; i < n; i++) scanf("%lf%lf", &R[i].x, &R[i].y); int cnt = ConvexHull(R, n, P); P[cnt] = P[0]; double S, C; GetMinRCarea(P, cnt, S, C); printf("%.2lf %.2lf\n", S, C); } return 0;}
0 0
- uva 12307(点集的外接矩形)
- OpenCV学习笔记(3):点集的最小外接矩形/圆,RNG类
- 点的外接矩形最小周长和面积模板
- ArcMap求四至点坐标的方法(最小外接矩形范围)
- opencv 连通区域的最小外接矩形
- UVA10173(求凸包的面积最小外接矩形)
- 图像的凸包、外接矩形
- 获取轮廓的最小外接矩形
- 要素外接矩形的四个角点坐标、长度、宽度、面积如何计算到要素属性表中?
- uva 1312 一个矩形中的最大的子矩形(其中不能包含某些点)
- 求解最小外接矩形
- cvMinAreaRect2外接矩形
- 求解最小外接矩形
- 最小外接矩形(MBR)
- OpenCV最小外接矩形
- 【opencv】轮廓外接矩形
- /*外接矩形部分*/
- Matlab 最小外接矩形
- 测试用例设计白皮书--场景设计方法
- java设计模式(9) - 适配器模式
- 排序小试牛刀(类冒泡……)
- UDK控制台命令概览
- 数据可视化中的图形选择
- uva 12307(点集的外接矩形)
- MFC多线程各种线程用法
- 测试用例设计白皮书--测试用例设计综合策略
- Java中的字符串
- poj2386水洼dfs
- 十一讲,买花
- HDU 5020 Revenge of Collinearity(枚举)
- UNP卷一I/O口复用中对图6.9程序的讨论(尤其是该程序不支持批量输入的缺点)
- 蓝桥网 概率计算 题解