POJ 1584--A Round Peg in a Ground Hole

20 篇文章 0 订阅

题意:给定一多边形和一圆,问多边形是否是凸包,且圆能否放在多边形内。

  1. 判断一多边形是否是凸多边形,可以枚举连续的三点组成的两个向量的旋转方向,即向量差积的正负,看所有的旋转方向是否一致。如果有旋转方向相反的边,说明存在凹陷。此处注意的是,题目的输入可能有三点共线的情况,所以要忽略共线的情况再判断旋转方向是否一致,且一定要有旋转。
  2. 判断圆心是否在多边形内,仍然使用差积的方法,可以证明在凸包内一点P以及边AB,依次枚举差积ABXAP的符号应该是一致的,且不能存在共线即P在边上的情况。
  3. 利用圆的切线性质,如果圆心到所有边的最短距离大于等于圆的半径,则圆能放在多边形内,反之不行。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define square(x) ((x)*(x))

struct node
{
    float x,y;
};
node* vertex;
node center;
int vertexNum;
float r;

float direction(node p1,node p2,node p3)         //差积
{
    return (p3.x-p1.x)*(p2.y-p1.y)-(p3.y-p1.y)*(p2.x-p1.x);
}

bool IsConvex()
{
    int i;
    float d,tmpD;
    d = 0;
    for(i = 0;i < vertexNum;i++)
    {
        tmpD = direction(vertex[i],vertex[i+1],vertex[i+2]);
        if(d*tmpD < 0)            //只向一个方向旋转,注意三点共线情况
            return false;
        if(tmpD != 0)
        d = tmpD;
    }
    if(d != 0)          //排除所有点共线的情况
        return true;
    else
        return false;
}

float modulo(node p1,node p2)           //向量求模
{
    return sqrt(square(p2.x-p1.x)+square(p2.y-p1.y));
}

bool IsCenterInConvex()
{
    float d,tmpD;
    for(int i = 0;i < vertexNum;i++)
    {
        tmpD = direction(vertex[i],center,vertex[i+1]);            //AB差乘AP
        if(tmpD == 0||((i != 0)&&(tmpD*d < 0)))     //AP总在AB的一个方向,且不能共线
            return false;
        d = tmpD;
    }
    return true;
}

float calcMinDis()
{
    float minDis = 1e6;
    float tmpDis;
    int i;
    for(i = 0;i < vertexNum;i++)
    {
        tmpDis = fabs(direction(center,vertex[i],vertex[i+1])/modulo(vertex[i],vertex[i+1]));    //点到直线距离
        if(minDis > tmpDis)
            minDis = tmpDis;
    }
    return minDis;
}

int main()
{
    int i;
    while(~scanf("%d",&vertexNum)&&vertexNum >= 3)
    {
        scanf("%f%f%f",&r,¢er.x,¢er.y);
        vertex = new node[vertexNum+2];
        for(i = 0;i < vertexNum;i++)
        {
            scanf("%f%f",&vertex[i].x,&vertex[i].y);
        }
        vertex[vertexNum] = vertex[0];
        vertex[vertexNum+1] = vertex[1];
        if(!IsConvex())             //多边形不是凸包
        {
            printf("HOLE IS ILL-FORMED\n");
            continue;
        }
        if(!IsCenterInConvex()||calcMinDis() < r)    //点在多边形外或者点到多边形距离小于圆半径
        {
            printf("PEG WILL NOT FIT\n");
            continue;
        }
        printf("PEG WILL FIT\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值