PKU 1584

PKU 1584
一道思路很简单的计算几何题目,就是先判是不是“凸多边形”,然后计算点到直线的最短距离。但是我错了很多次。一个问题就是有可能peg不在多边形内,这要单独判断一下;还有一个问题找了很久才发现,原来题目中说满足条件的多边形不是纯粹的凸多边形,题目中的多边形是“任意内部两点连线不会和多边形的边相交”,这样如果多边形的多个顶点存在共线的情况,其实也是可以的,但是我误以为就是正常的凸多边形,结果狂WA
以后读题还是得仔细啊,考虑问题要全面。。
PKU 1584
#include <cstdio>
#include 
<cmath>
const int N = 128;
const double eps = 1e-6, PI = acos(-1.0);

struct point
{
    
double x, y;
    point 
operator - (const point &p)const
    
{
        point tmp;
        tmp.x 
= x - p.x;
        tmp.y 
= y - p.y;
        
return tmp;
    }

    
double operator * (const point &p)const
    
{
        
return x * p.y - y * p.x;
    }

}
;

int dblcmp(double a)
{
    
if (fabs(a) < eps)  return 0;
    
return a > 0 ? 1 : -1;
}

double dot(const point &p1, const point &p2)
{
    
return p1.x * p2.x + p1.y * p2.y;
}

double relation(const point &a, const point &b, const point &c)
{
    
return dot(c - a, b - a) / ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
}

point perpendicular(
const point &a, const point &b, const point &c)
{
    
double r;
    point p;

    r 
= relation(a, b, c);
    p.x 
= (1.0 - r) * a.x + r * b.x;
    p.y 
= (1.0 - r) * a.y + r * b.y;

    
return p;
}

double angel(const point &o, const point &a, const point &e)
{
    point oa, oe;
    
double r, up, down;

    oa 
= a - o;
    oe 
= e - o;
    up 
= oa.x * oe.x + oa.y * oe.y;
    down 
= (oa.x * oa.x + oa.y * oa.y) * (oe.x * oe.x + oe.y * oe.y);

    r 
= up / sqrt(down);
    
if (r >= 1.0)
        
return 0;
    
if (r <= -1.0)
        
return -1.0 * PI;
    
/**//*3点共线情况*/

    
if (dblcmp((a - o) * (e - o)) > 0//判方向
        return acos(r);
    
else
        
return -1.0 * acos(r);
}

int pointInPolygon(point pointset[], int n, point p)
{
    
double a = 0;

    
for (int i = 0; i < n; i++)
    
{
        
double tmp = dblcmp((pointset[i] - p) * (pointset[(i+1)%n] - p));
        
if (tmp != 0)
            a 
+= angel(p, pointset[i], pointset[(i+1)%n]);
    }


    
if (dblcmp(a) == 0)                     //点在外转角和为0
        return 0;
    
else if (dblcmp(fabs(a) - 2.0 * PI) == 0)     //点在内转角和为2*PI
        return 2;
    
else
        
return 1;
}

double dis(const point &p1, const point &p2)
{
    
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

double pointToSegment(const point &a, const point &b, const point &c)
{
    point p;
    
if (relation(a, b, c) <= 0)
        
return dis(a, c);
    
else if (relation(a, b, c) >= 1)
        
return dis(b, c);
    
else
    
{
        p 
= perpendicular(a, b, c);
        
return dis(p, c);
    }

}

bool is_convex(point p[N], int n)
{
    
double tmp = (p[1- p[0]) * (p[2- p[0]);
    
for (int i = 1; i < n; i++)
        
if (dblcmp((p[(i+1)%n] - p[i]) * (p[(i+2)%n] - p[i]) * tmp) < 0)
            
return false;
    
return true;
}


int main()
{
    
int n, i;
    
double r;
    point peg, p[N];

    
while (scanf("%d"&n) == 1 && n >= 3)
    
{
        scanf(
"%lf %lf %lf"&r, &peg.x, &peg.y);
        
for (i = 0; i < n; i++)
            scanf(
"%lf %lf"&p[i].x, &p[i].y);
        
if (!is_convex(p, n))
        
{
            puts(
"HOLE IS ILL-FORMED");
            
continue;
        }

        
for (i = 0; i < n; i++)
            
if (dblcmp(pointToSegment(p[i], p[(i+1)%n], peg) - r) < 0)
                
break;
        printf(
"%s\n", i == n && pointInPolygon(p, n, peg) == 2 ? "PEG WILL FIT" : "PEG WILL NOT FIT");
    }


    
return 0;
}

你可能感兴趣的:(PKU 1584)