【POJ 1584】 A Round Peg in a Ground Hole (判凸包+判圆在凸包内)
这题题面是一大坑。。长长的 明显是给我这种英语渣准备的。。。
大体意思是给出一个多边形的点 按顺时针或逆时针给出 判断是否为凸包 同时给出一个圆(圆心坐标+半径) 问这个圆在不在多边形内
首先顺逆时针不确定 我的做法是输入时先判断顺时针还是逆时针输入 然后统统变成逆时针来走 就是根据两种情况传入不同的枚举起点 终点 和加减(具体见代码
判凸包用建凸包的叉成法即可 既然逆时针走 那么如果是凸包 向量一定是逆时针转动 同时还可以判断圆心是不是在凸包内 看当前起点与圆心的向量叉成当前边 为负(顺时针) 说明圆心在多边形内(边上也算 因为圆半径有0的情况
如果不为凸包 直接输出 HOLE IS ILL-FORMED
如果圆心不在凸包内 输出PEG WILL NOT FIT
否则再判断圆是否完全被凸包包裹 枚举凸包每个边即可 如果出现某条边与圆心距离小于圆的半径 说明圆不再凸包内 如果能遍历完所有边 则在凸包内
求点到线段的距离用线段两段点与改点构成的向量进行叉乘 由于构成三角形 并且点到线段距离是三角形高 所以可以得出 (h*w)/2 = l1xl2/2 w为线段长度 x为叉乘 叉乘得到的是平行四边形面积 所以需要除2 化简可得 h = (l1xl2)/w 这就是点到线段的距离公式
至此 程序完成
PS:发现个好东西 大家WA不要不要了的可以去测测
http://midatl.fireduck.com/archive/2003/problems/MidAtlantic-2003/problem-D/
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <algorithm> #include <cmath> #define esp 1e-5 using namespace std; typedef struct Point Point; typedef struct Line Line; struct Line { double x,y; bool operator > (const Line a)const//顺时针 { return x*a.y-y*a.x > esp; } bool operator < (const Line a)const//逆时针 { return x*a.y-y*a.x < -esp; } bool operator == (const Line a)const//共线 { return x*a.y-y*a.x < esp && x*a.y-y*a.x > -esp; } double operator * (const Line a)const//叉乘 { return fabs(x*a.y-y*a.x); } }; struct Point { double x,y; Line operator - (const Point a)const//得到两点向量 { Line l; l.x = x-a.x; l.y = y-a.y; return l; } double operator + (const Point a)const//两点间距离 { return (x-a.x)*(x-a.x)+(y-a.y)*(y-a.y); } }; Point yx; double r; vector <Point> vc; int n; int cal(int low,int high,int stp)//判断是否为凸多边形 同时判断圆心是否在内部 { Line l1,l2; Point p1,p2,p3; int i; int f = 1; p1 = vc[low]; p2 = vc[low+stp]; l1 = p2-p1; l2 = yx-p1; if(l2 > l1) f = 0; for(i = low+stp*2; i != high+stp; i += stp) { p3 = vc[i]; l1 = p2-p1; l2 = p3-p1; if(l2 > l1) return 0; l1 = p3-p2; l2 = yx-p2; if(f && l2 > l1) f = 0; p1 = p2; p2 = p3; } return f+1; } bool Challenge()//判断圆是否在多边形内 { int i; Point p; Line l1,l2; p = vc[0]; for(i = 1; i < vc.size(); ++i) { l1 = p-yx; l2 = vc[i]-yx; if((l1*l2)/sqrt(vc[i]+p) - r < -esp) return 0; p = vc[i]; } return 1; } int main() { freopen("in.in","r",stdin); Point tmp,pt,p1,p2; Line l1,l2; int f; while(~scanf("%d",&n) && n >= 3) { f = 0; vc.clear(); scanf("%lf %lf %lf",&r,&yx.x,&yx.y); scanf("%lf %lf",&tmp.x,&tmp.y); vc.push_back(tmp); p1 = tmp; scanf("%lf %lf",&p2.x,&p2.y); vc.push_back(p2); n -= 2; while(n--) { scanf("%lf %lf",&pt.x,&pt.y); vc.push_back(pt); if(!f) { l1 = p2 - p1; l2 = pt - p1; if(l1 > l2) f = 1; else if(l1 < l2) f = -1; } p1 = p2; p2 = pt; } vc.push_back(tmp); if(f == 1) f = cal(0,vc.size()-1,1);//顺时针输入 else if(f == -1) f = cal(vc.size()-1,0,-1);//逆时针输入 else f = 0;//未构成凸多边形 if(f == 2) { if(Challenge()) puts("PEG WILL FIT"); else puts("PEG WILL NOT FIT"); } else if(f == 1) puts("PEG WILL NOT FIT"); else puts("HOLE IS ILL-FORMED"); } return 0; }
小记:
这么晚写这个题解 觉得自己也蛮拼的 明天上午结训会 还要上去讲话(不是你们想的呢样。。我是棵青葱。。。锻炼锻炼吧也算
至此 训练计划POJ部分初级结束 在这深夜 时间好快 从去年暑假 到现在 一年时光 我也为自己的进步惊讶 但确实不够 只能说稍微比一般人快一点 跟那些大牛学校比 。。。。只能呵呵然后被虐……多校就能看得出 还有前一次跟山科一同做了份网赛(组队 确实比人家弱很多 跟他们14级的比也是 差太多了 也算常态吧 往往什么事都是这样 越努力 云雾越会消散 然而渐渐的你却发现 面前是堵高墙 想要继续 就要不断爬 可翻过高墙 你又发现后面有条河 有过河又看到座高山。。。
就是这样 这个金字塔没有顶层 只有不断地筑高 没有人知道会爬多高 也没有尽头 然而弱还在塔底呢。。。
在这小小感慨一下。应该都看不到吧。。。看不到我看不到我看不到我……既然选择了这条路 爬着跪着算什么 至少还在前行 就是好的!
版权声明:本文为博主原创文章,未经博主允许不得转载。