A Round Peg in a Ground Hole - POJ 1584 (判断凸多边形&判断点在多边形内&判断圆在多边形内)
2015-09-10 23:29
429 查看
题目大意:首先给一个圆的半径和圆心,然后给一个多边形的所有点(多边形按照顺时针或者逆时针给的),求,这个多边形是否是凸多边形,如果是凸多边形在判断这个圆是否在这个凸多边形内。
分析:判断凸多边形可以使用相邻的三个点叉积判断,因为不知道顺时针还是逆时针,所以叉积如果有有整数和负数,那么一定不是凸多边形(注意允许多多点在一条线段上)。判断圆在凸多边形首先要判断圆心是否在多边形内,如果在多边形内,再次判断圆心到达到变形每条边的最短距离,如果小于半径就是不合法。ps:一道好题,通过这个题学会了不少东西。
代码如下:
=======================================================================================================================================
分析:判断凸多边形可以使用相邻的三个点叉积判断,因为不知道顺时针还是逆时针,所以叉积如果有有整数和负数,那么一定不是凸多边形(注意允许多多点在一条线段上)。判断圆在凸多边形首先要判断圆心是否在多边形内,如果在多边形内,再次判断圆心到达到变形每条边的最短距离,如果小于半径就是不合法。ps:一道好题,通过这个题学会了不少东西。
代码如下:
=======================================================================================================================================
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; const int MAXN = 1e3+7; const double EPS = 1e-8; const double oo = 1e10+7; struct Point { double x, y; Point(double x=0, double y=0):x(x),y(y){} Point operator - (const Point &tmp)const{ return Point(x-tmp.x, y-tmp.y); } double operator ^(const Point &tmp)const{ return x*tmp.y - y*tmp.x; } double operator *(const Point &tmp)const{ return x*tmp.x + y*tmp.y; } }; double Dist(Point a, Point b) {///两点间的距离 return sqrt((a-b)*(a-b)); } int Sign(double t) { if(t > EPS)return 1; if(fabs(t) < EPS)return 0; return -1;///负数 } struct Segment { Point S, E; Segment(Point S=0, Point E=0):S(S), E(E){} bool OnSeg(const Point &p) {///点是否在线段上 if(Sign( (S-E)^(p-E) ) == 0)///共线 if(Sign( (p.x-S.x)*(p.x-E.x) ) <= 0)///位于线段的中间或者端点 if(Sign( (p.y-S.y)*(p.y-E.y) ) <= 0) return true; return false; } bool Inter(const Segment &tmp) {///只考虑完全相交的情况 return Sign((S-E)^(tmp.S-E)) * Sign((S-E)^(tmp.E-E)) == -1; } Point NearPoint(const Point &p) {///点到线段最近的点 Point res; double r = ((E-S)*(p-S)) / ((E-S)*(E-S)); if(r > EPS && (1.0 - r) > EPS ) {///点在线段的投影在线段上 res.x = S.x + r * (E.x-S.x); res.y = S.y + r * (E.y-S.y); } else {///求离最近的端点 if(Dist(p, S) < Dist(p, E)) res = S; else res = E; } return res; } }; struct Poly { int N; Point vertex[MAXN]; bool IsConvex() {///判断是否是凸多边形,可以共线 int vis[3] = {0}; for(int i=0; i<N; i++) {///如果同时出现整数和负数,说明存在凹的 int k = Sign((vertex[(i+1)%N]-vertex[i])^(vertex[(i+2)%N]-vertex[i])); vis[k+1] = 1; if(vis[0] && vis[2]) return false; } return true; } int InPoly(const Point &Q) {///判断点Q是否在多边形内,射线法,奇数在内,偶数在外 ///在圆上返回0, 圆外-1, 圆内 1 Segment ray(Point(-oo, Q.y), Q);///构造射线的最远处 int cnt=0;///统计相交的边数 for(int i=0; i<N; i++) { Segment edge(vertex[i], vertex[(i+1)%N]); if(edge.OnSeg(Q) == true) return 0;///点在边上 if(ray.OnSeg(vertex[i]) == true) {///如果相交连接点,那么取y值小的点 if(vertex[(i+1)%N].y - vertex[i].y > EPS) cnt++; } else if(ray.OnSeg(vertex[(i+1)%N]) == true) { if(vertex[i].y - vertex[(i+1)%N].y > EPS) cnt++; } else if(ray.Inter(edge) && edge.Inter(ray)) cnt++; } if(cnt % 2) return 1; else return -1; } }; struct Circle { Point center;///圆心 double R;///半径 }; bool Find(Poly &a, Circle &c) {///判断圆是否在多边形内 if(a.InPoly(c.center) == -1) return false;///如果圆心在多边形外面 for(int i=0; i<a.N; i++) { Segment edge(a.vertex[i], a.vertex[(i+1)%a.N]); double len = Dist(c.center, edge.NearPoint(c.center)); if(Sign(len-c.R) < 0) return false; } return true; } int main() { Poly a;///定义多边形 Circle c;///定义圆 while(scanf("%d", &a.N) != EOF && a.N > 2) { scanf("%lf%lf%lf", &c.R, &c.center.x, &c.center.y); for(int i=0; i<a.N; i++) scanf("%lf%lf", &a.vertex[i].x, &a.vertex[i].y); if(a.IsConvex() == false) printf("HOLE IS ILL-FORMED\n"); else if(Find(a, c) == false) printf("PEG WILL NOT FIT\n"); else printf("PEG WILL FIT\n"); } return 0; }
相关文章推荐
- Java内部类的作用
- 第54讲:Scala中复合类型实战详解
- linux 之df 和du
- 解决No “rule to make target `../Database/images/login.png', needed by `debug/qrc_image.cpp'. Stop.”
- Andrew Ng机器学习课程9
- 定时器.倒计时
- java之常量池
- C++数据结构之链式队列(Linked Queue)
- .net 的一个分词系统(jieba中文分词的.NET版本:jieba.NET)
- C语言位运算详解
- C语言位运算详解
- 蒜头爬楼梯
- hdu 1866 几个矩形面积的和 ***
- EF基础概念篇1
- 免费学习编程的 12 个地方
- android自定义布局中的平滑移动
- 一次快速排序错误引发的思考(1)
- Android Studio出现Gradle '×××' project refresh failed 解决办法
- MySQL 基础操作语法
- 软件研发:公司内部技术考试——答题方法