POJ1584 A Round Peg in a Ground Hole

来源:互联网 发布:nginx conf 配置 编辑:程序博客网 时间:2024/06/05 20:00

一.原题链接:

http://poj.org/problem?id=1584

二.题目大意:

抽象出来就是给出一个圆心和半径,再按顺序给出n个点,问:

  • 若给出的n个点不能按顺序连成凸包,输出”HOLE IS ILL-FORMED”
  • 若给出n个点可以连成凸包,并且给出的圆在凸包内,输出”PEG WILL FIT”
  • 若给出n个点可以连成凸包,并且给出的圆不在凸包内,
    输出”PEG WILL NOT FIT”

三.解题思路:

显而易见:
1. 先判断是否可以连成凸包
2. 再判断圆心是否在凸包里面
3. 再算出圆心到多边形各边的距离
1,2,3满足上一步才进行下一步。

首先介绍叉乘性质:
对于共起点有序向量二元组(a⃗ ,b⃗ ),其旋转方向为:使 a⃗  能够旋转一个小于 180 度的角并与 b⃗  重合的方向。若a⃗ ×b⃗ <0,则旋转方向为顺时针,a⃗ ×b⃗ >0,为逆时针。

  • 判断n个点是否可以依次连成凸包:
    对于n个点p1,p2...pn,依次连接成向量p1p2,...pn1pn,pnp1将它们前后做叉乘,如果符号都相同,则这n个点可依次连成凸包。符号都相同说明绕着一个方向旋转,自己想象一下。
  • 判断圆心是否在多边形里面:
    圆心o依次连接多边形的点成向量op1op2...opn,将它们前后做叉乘,如果符号都相同,说明圆心在多边形内,有一个为0说明圆心在边上。
  • 判断圆是否在多边形里面:
    由于之前已经确定圆心在多边形里面,于是圆心到线段距离等于圆心到线段所在直线距离,直接求所有的距离中最短的距离与半径对比就可以了。

四.代码:

import java.util.ArrayList;import java.util.List;import java.util.Scanner;class Main {    static final int MAX_SIZE = 50;    static final double INF = 1e40;    static final double ESP = 1e-4;    static int vertexNum;    static double radius;    static Point circleCenter = new Point();    static Point[]  polygonPoints;    static double cross(Vector v1, Vector v2){        return v1.x*v2.y - v2.x*v1.y;    }    static double distToLine(Point p, Line l){        return Math.abs((l.a*p.x + l.b*p.y + l.c)/                Math.sqrt(l.a*l.a + l.b*l.b));    }    static boolean convexHull(){        Vector v1 = new Vector(), v2 = new Vector();        v1.setXY(polygonPoints[0], polygonPoints[1]);        v2.setXY(polygonPoints[1], polygonPoints[2]);        boolean positive;        if(cross(v1, v2) < 0){            positive = false;        } else {            positive = true;        }        for(int i = 1; i < vertexNum-2; i++){            v1.setXY(polygonPoints[i], polygonPoints[i+1]);            v2.setXY(polygonPoints[i+1], polygonPoints[i+2]);            double res = cross(v1, v2);            if(res<0&&positive || res>0&&!positive){                return false;            }        }        v1.setXY(polygonPoints[vertexNum-2], polygonPoints[vertexNum-1]);        v2.setXY(polygonPoints[vertexNum-1], polygonPoints[0]);        double res = cross(v1, v2);        if(res<0&&positive || res>0&&!positive){            return false;        }        return true;    }    static boolean centerInPolygon(){        Vector v1 = new Vector(), v2 = new Vector();        v1.setXY(circleCenter, polygonPoints[0]);        v2.setXY(circleCenter, polygonPoints[1]);        boolean positive;        if(cross(v1, v2) < 0){            positive = false;        } else {            positive = true;        }        for(int i = 1; i < vertexNum-1; i++){            v1.setXY(circleCenter, polygonPoints[i]);            v2.setXY(circleCenter, polygonPoints[i+1]);            double res = cross(v1, v2);            if(res<0&&positive || res>0&&!positive ||                    res == 0 && radius > 0){                return false;            }        }        return true;    }    static double getMinDist(){        Line line = new Line();        double[] parameter = new double[3];        double minDist = INF;        for(int i = 0; i < vertexNum-1; i++){            line.setPoint(polygonPoints[i], polygonPoints[i+1]);            line.getParameter(parameter);            minDist = Math.min(minDist, distToLine(circleCenter, line));        }        return minDist;    }    public static void main (String args[]){        Scanner in = new Scanner(System.in);        double x, y;        while(true){            vertexNum = in.nextInt();            if(vertexNum < 3){                break;            }            radius = in.nextDouble();            x = in.nextDouble();            y = in.nextDouble();            circleCenter.setXY(x, y);            polygonPoints = new Point[vertexNum];            for(int i = 0; i < vertexNum; i++){                x = in.nextDouble();                y = in.nextDouble();                polygonPoints[i] = new Point();                polygonPoints[i].setXY(x, y);            }            if(!convexHull()){                System.out.println("HOLE IS ILL-FORMED");            } else if (!centerInPolygon() || radius > getMinDist()){                System.out.println("PEG WILL NOT FIT");            } else{                System.out.println("PEG WILL FIT");            }        }        in.close();    }}class Point{    public void setXY(double x, double y) {        this.x = x;        this.y = y;    }    public double x, y;}class Segment{    public Point a = new Point();    public Point b = new Point();}class Line{    public void setPoint(Point b, Point e){        this.begin = b;        this.end = e;    }    public void getParameter(double[] parameter){        a = begin.y-end.y;        b = end.x-begin.x;        c = begin.x*end.y - end.x*begin.y;    }    public double a, b, c;    public Point begin = new Point();    public Point end = new Point();}class Vector{    public void setXY(Point begin, Point end) {        this.x = end.x-begin.x;        this.y = end.y-begin.y;    }    public Vector reVector() {        Vector v = new Vector();        v.x = -x;        v.y = -y;        return v;    }    public double x, y;}
0 0
原创粉丝点击