题意:已知一个多边形的n个顶点坐标,然后再给一个钉子,给定钉子的半径和圆心坐标,首先判断多边形是否为凸多边形,若为凸多边形,再判断钉子是否可以放到凸多边形内部。

思路:
1.由于顶点给出的顺序可能为逆时针或顺时针,所以在判断是否为凸边形,利用叉积的性质,每个点依次扫描看是否都顺着同一的方向转动。
2.判断圆(钉子)是否在多边形内部,第一步判断圆心是否在凸多边形内部(以圆心为定点扫描一周),第二步再判断圆心到某一边的最短距离,若存在某最短距离大于圆心,则圆不能放在凸多边内。
或者思路可以参考这个:
http://blog.csdn.net/lyy289065406/article/details/6648606

#include <stdlib.h>
#include <math.h>
#include <iostream> #define MAXN 1000
#define offset 10000
#define eps 1e-8
#define zero(x) (((x)>0?(x):-(x))<eps)
#define _sign(x) ((x)>eps?1:((x)<-eps?2:0)) struct point{ double x, y; };
struct line{ point a, b; }; double xmult(point p1, point p2, point p0){
return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
} //判定凸多边形,顶点按顺时针或逆时针给出,允许相邻边共线
bool is_convex(int n, point* p){
int i, s[3] = { 1, 1, 1 };
for (i = 0; i < n && s[1] | s[2]; i++)
s[_sign(xmult(p[(i + 1)%n], p[(i + 2)%n], p[i]))] = 0;
return s[1] | s[2];
} //判定凸多边形,顶点按顺时针或逆时针给出,不允许相邻边共线
bool is_convex_v2(int n, point* p){
int i, s[3] = { 1, 1, 1 };
for (i = 0; i < n && s[0] && s[1] | s[2]; i++)
s[_sign(xmult(p[(i + 1)%n], p[(i + 2)%n], p[i]))] = 0;
return s[0] && s[1] | s[2];
} //判点在凸多边形内或多边形边上,顶点按顺时针或逆时针给出
bool inside_convex(point q, int n, point* p){
int i, s[3] = { 1, 1, 1 };
for (i = 0; i < n && s[1] | s[2]; i++)
s[_sign(xmult(p[(i + 1)%n], q, p[i]))] = 0;
return s[1] | s[2];
} //判点在凸多边形内,顶点按顺时针或逆时针给出,在多边形边上返回0
bool inside_convex_v2(point q, int n, point* p){
int i, s[3] = { 1, 1, 1 };
for (i = 0; i < n && s[0] && s[1] | s[2]; i++)
s[_sign(xmult(p[(i + 1)%n], q, p[i]))] = 0;
return s[0] && s[1] | s[2];
} //判点在任意多边形内,顶点按顺时针或逆时针给出
//on_edge表示点在多边形边上时的返回值,offset为多边形坐标上限
bool inside_polygon(point q, int n, point* p, int on_edge = 1){
point q2;
int i = 0, count;
while (i < n)
for (count = i = 0, q2.x = rand() + offset, q2.y = rand() + offset; i < n; i++)
if (zero(xmult(q, p[i], p[(i + 1)%n])) && (p[i].x - q.x)*(p[(i + 1)%n].x - q.x) < eps && (p[i].y - q.y)*(p[(i + 1)%n].y - q.y) < eps)
return on_edge;
else if (zero(xmult(q, q2, p[i])))
break;
else if (xmult(q, p[i], q2)*xmult(q, p[(i + 1)%n], q2) < -eps && xmult(p[i], q, p[(i + 1)%n])*xmult(p[i], q2, p[(i + 1)%n]) < -eps)
count++;
return count & 1;
} inline bool opposite_side(point p1, point p2, point l1, point l2){
return xmult(l1, p1, l2)*xmult(l1, p2, l2) < -eps;
} inline bool dot_online_in(point p, point l1, point l2){
return zero(xmult(p, l1, l2)) && (l1.x - p.x)*(l2.x - p.x) < eps && (l1.y - p.y)*(l2.y - p.y) < eps;
} //判线段在任意多边形内,顶点按顺时针或逆时针给出,与边界相交返回1
bool inside_polygon(point l1, point l2, int n, point* p){
point t[MAXN], tt;
int i, j, k = 0;
if (!inside_polygon(l1, n, p) || !inside_polygon(l2, n, p))
return 0;
for (i = 0; i < n; i++)
if (opposite_side(l1, l2, p[i], p[(i + 1)%n]) && opposite_side(p[i], p[(i + 1)%n], l1, l2))
return 0;
else if (dot_online_in(l1, p[i], p[(i + 1)%n]))
t[k++] = l1;
else if (dot_online_in(l2, p[i], p[(i + 1)%n]))
t[k++] = l2;
else if (dot_online_in(p[i], l1, l2))
t[k++] = p[i];
for (i = 0; i < k; i++)
for (j = i + 1; j < k; j++){
tt.x = (t[i].x + t[j].x) / 2;
tt.y = (t[i].y + t[j].y) / 2;
if (!inside_polygon(tt, n, p))
return 0;
}
return 1;
} double distance(point p1, point p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
double disptoline(point p, point l1, point l2){
return fabs(xmult(p, l1, l2)) / distance(l1, l2);
}
int intersect_seg_circle(point c, double r, point l1, point l2){
double t1 = distance(c, l1) - r, t2 = distance(c, l2) - r;
point t = c;
if (t1<eps || t2<eps)
return t1>-eps || t2>-eps;
t.x += l1.y - l2.y;
t.y += l2.x - l1.x;
return xmult(l1, c, t)*xmult(l2, c, t) < eps && disptoline(c, l1, l2) - r < eps;
}
//判断圆是否在多边形内
bool circle_in_polygen(double r, point o, int n, point *p)
{
for (int i = 1; i < n; i++)
{
bool flag = intersect_seg_circle(o, r, p[i - 1], p[i]);
if (flag) { return false; break; }
}
return true;
} point intersection(line u, line v){
point ret = u.a;
double t = ((u.a.x - v.a.x)*(v.a.y - v.b.y) - (u.a.y - v.a.y)*(v.a.x - v.b.x))
/ ((u.a.x - u.b.x)*(v.a.y - v.b.y) - (u.a.y - u.b.y)*(v.a.x - v.b.x));
ret.x += (u.b.x - u.a.x)*t;
ret.y += (u.b.y - u.a.y)*t;
return ret;
} point barycenter(point a, point b, point c){
line u, v;
u.a.x = (a.x + b.x) / 2;
u.a.y = (a.y + b.y) / 2;
u.b = c;
v.a.x = (a.x + c.x) / 2;
v.a.y = (a.y + c.y) / 2;
v.b = b;
return intersection(u, v);
} //多边形重心
point barycenter(int n, point* p){
point ret, t;
double t1 = 0, t2;
int i;
ret.x = ret.y = 0;
for (i = 1; i<n - 1; i++)
if (fabs(t2 = xmult(p[0], p[i], p[i + 1]))>eps){
t = barycenter(p[0], p[i], p[i + 1]);
ret.x += t.x*t2;
ret.y += t.y*t2;
t1 += t2;
}
if (fabs(t1) > eps)
ret.x /= t1, ret.y /= t1;
return ret;
} int main()
{
int n;
double pegR;
point peg;
while (std::cin >> n && (n >= 3))
{
std::cin >> pegR >> peg.x >> peg.y;
point p[155];
for (int i = 0; i < n; i++)
{
std::cin >> p[i].x >> p[i].y;
}
bool flag = is_convex(n, p);
bool flag2 = inside_convex_v2(peg, n, p);
bool flag3 = circle_in_polygen(pegR, peg, n, p); if (!flag)
std::cout << "HOLE IS ILL-FORMED" << std::endl;
else
{
if (flag2 && flag3)
std::cout << "PEG WILL FIT" << std::endl;
else
std::cout << "PEG WILL NOT FIT" << std::endl;
}
}
}

poj1584的更多相关文章

  1. POJ1584 A Round Peg in a Ground Hole 凸包判断 圆和凸包的关系

    POJ1584 题意:给定n条边首尾相连对应的n个点 判断构成的图形是不是凸多边形 然后给一个圆 判断圆是否完全在凸包内(相切也算) 思路:首先运用叉积判断凸多边形 相邻三条边叉积符号相异则必有凹陷 ...

  2. poj1584(判断凸包+求点到线段的距离)

    题目链接:https://vjudge.net/problem/POJ-1584 题意:首先要判断凸包,然后判断圆是否在多边形中. 思路: 判断凸包利用叉积,判断圆在多边形首先要判断圆心是否在多边形中 ...

  3. POJ1584 判断多边形是否为凸多边形,并判断点到直线的距离

    求点到直线的距离: double dis(point p1,point p2){   if(fabs(p1.x-p2.x)<exp)//相等的  {    return fabs(p2.x-pe ...

  4. poj1584 A Round Peg in a Ground Hole 判断多边形凹凸,点到线的距离【基础计算几何】

    大致思路:首先对于所给的洞的点,判断是否是凸多边形,图形的输入和输出可以是顺时针或者逆时针,而且允许多点共线 Debug 了好几个小时,发现如下问题 判断三点是否共线,可用斜率公式判断 POINT p ...

  5. poj1584 A round peg in a ground hole【计算几何】

    含[判断凸包],[判断点在多边形内],[判断圆在多边形内]模板  凸包:即凸多边形 用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点. The ...

  6. poj分类 很好很有层次感。

    初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      ( ...

  7. 【转】POJ题目分类推荐 (很好很有层次感)

    OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)初期: 一. ...

  8. 【转】ACM训练计划

    [转] POJ推荐50题以及ACM训练方案 -- : 转载自 wade_wang 最终编辑 000lzl POJ 推荐50题 第一类 动态规划(至少6题, 和 必做) 和 (可贪心) (稍难) 第二类 ...

  9. POJ 题目分类(转载)

    Log 2016-3-21 网上找的POJ分类,来源已经不清楚了.百度能百度到一大把.贴一份在博客上,鞭策自己刷题,不能偷懒!! 初期: 一.基本算法: (1)枚举. (poj1753,poj2965 ...

随机推荐

  1. I.MX6 shutdown by software

    /************************************************************************ * I.MX6 shutdown by softwa ...

  2. KM算法(二分图的最佳完美匹配)

    KM算法大概过程: (1)初始化Lx数组为该boy的一条权值最大的出边.初始化Ly数组为 0. (2)对于每个boy,用DFS为其找到一个girl对象,顺路记录下S和T集,并更新每个girl的slac ...

  3. android layoutparams应用指南(转)

    LayoutParams相当于一个Layout的信息包,它封装了Layout的位置.高.宽等信息.假设在屏幕上一块区域是由一个Layout占领的,如果将一个View添加到一个Layout中,最好告诉L ...

  4. 10个实用的PHP正则表达式 (转)

    http://www.iteye.com/news/23231 1. 验证E-mail地址 这是一个用于验证电子邮件的正则表达式.但它并不是高效.完美的解决方案.在此不推荐使用. $email = & ...

  5. 【英文】Bingo口语笔记(18) - Cover系列

    cover charge 服务费 cover version 翻唱版本 cover the news 头条新闻

  6. MySQL存储过程中的3种循环

    在MySQL存储过程的语句中有三个标准的循环方式:WHILE循环,LOOP循环以及REPEAT循环.还有一种非标准的循环方式:GOTO,不过这种循环方式最好别用,很容易引起程序的混乱,在这里就不错具体 ...

  7. 【转】Linux设备驱动之mmap设备操作

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/08/2281222.html 1.mmap系统调用 void *mmap(void *addr, ...

  8. javascript对象之 selectionStart selectionEnd

    <script> function inserttag(){ var text=document.getElementById('con'); text.focus(); var star ...

  9. pageX,clientX,offsetX,layerX的区别

    pageX,clientX,offsetX,layerX的区别 在各个浏览器的JS中,有很多个让你十分囧的属性,由于各大厂商对标准的解释和执行不一样,导致十分混乱,也让我们这些前端攻城狮十分无语和纠结 ...

  10. MVC和WebApi 使用get和post 传递参数。

    我们总结一下用js请求服务器的传参方法. Get方式 Get主要是用来查询,一般分为无参,一个参数,多个参数,实体对象参数. 1.无参 //Get没有参数 var get_f1 = function( ...