zoukankan      html  css  js  c++  java
  • POJ1584A Round Peg in a Ground Hole

    转载请注明出处:優YoU  http://user.qzone.qq.com/289065406/blog/1309142308

     

    大致题意:

    按照顺时针或逆时针方向输入一个n边形的顶点坐标集,先判断这个n边形是否为凸包。

    再给定一个圆形(圆心坐标和半径),判断这个圆是否完全在n变形内部。

     

    解题思路:

    题意已经很直白了。。就是那个思路。。。

    注意输入完顶点集后,要封闭多边形,方便后面枚举边。

    封闭方法:

    定义点集数组Vectex[1~n]记录n个顶点,再令Vectex[0]=Vectex[n]Vectex[n+1]=Vectex[1]

     

    1、判断凸包:

       由于点集已经按某个时针方向有序,因此可以先定义一个方向系数direction=0

       两两枚举n边形的边,用叉积判断这两条边的转向(右螺旋或左螺旋),由于存在散点共线的情况,因此当且仅当叉积的值temp第一次不为0时,direction=tempdirection的值此后不再改变。(direction>0 则为右螺旋逆时针,direction<0则为左螺旋顺时针)

       此后继续枚举剩下的边,只要判断direction*temp>=0即可,当存在一个direction*temp<0的边,说明这是凹多边形,就不是凸包了。

    2、判断圆心与多边形的关系:

       用环顾法:

       设圆心为P,逐条枚举n边形的边AB,利用

     

       计算PAPB的夹角,最后求和得到的就是环顾角。

    (1)       圆心在多边形内部时,环顾角=±360

    (2)       圆心在多边形外部时,环顾角=0

    (3)       圆心在多边形边上时(不包括顶点),环顾角=±180

    (4)       圆心在多边形顶点时,环顾角为(0,360)之间的任意角,其实就是圆心所在的顶点的两条邻接边的夹角。

    3、当圆心在圆内时,判断圆与多边形的关系

       设圆心为P,逐条枚举n边形的边AB,利用得到△PAB的面积,

    再根据公式S=0.5*|AB|*h,可以得到 

     枚举所有h与圆的半径R比对,只要所有的边都有R-h>=0,则说明圆在多边形内

     

    Source修正:

    把原题的“Mid-Atlantic 2003修正为以下黑斜体内容,可用于找到本题的测试数据

    谷歌搜索:

    Index of /archive/2003/problems/MidAtlantic-2003

    http://midatl.fireduck.com/archive/2003/problems/

     

     

      1 //Memory Time
    2 //268K 0MS
    3
    4 #include<iostream>
    5 #include<cmath>
    6 using namespace std;
    7
    8 const double eps=1e-6;
    9 const double pi=3.141592654;
    10
    11 typedef class NODE
    12 {
    13 public:
    14 double x,y;
    15 }pos;
    16
    17 int n;
    18 double PegR; //钉子半径
    19 pos Peg; //钉子坐标
    20
    21 int precision(double x); //精度讨论
    22 double det(double x1,double y1,double x2,double y2); //叉积
    23 double dotdet(double x1,double y1,double x2,double y2); //点积
    24 double cross(pos A,pos B,pos C,pos D);
    25 double distant(pos A,pos B); //计算距离
    26 double angle(pos A,pos B,pos P); //计算向量PA与PB夹角
    27
    28 bool IsConvexBag(pos* Vectex); //判断输入的点集是否为凸包(本题保证了输入的点集为按某一时针方向有序)
    29 bool IsIn(pos* Vectex); //判断圆心是否在多边形内部
    30 bool IsFit(pos* Vectex); //判断圆的半径是否<=其圆心到多边形所有边的最小距离
    31
    32 int main(void)
    33 {
    34 while(cin>>n && n>=3)
    35 {
    36 cin>>PegR>>Peg.x>>Peg.y;
    37 pos* Vectex=new pos[n+2]; //多边形顶点坐标
    38
    39 for(int i=1;i<=n;i++)
    40 cin>>Vectex[i].x>>Vectex[i].y;
    41
    42 Vectex[0].x=Vectex[n].x; //封闭多边形
    43 Vectex[0].y=Vectex[n].y;
    44 Vectex[n+1].x=Vectex[1].x;
    45 Vectex[n+1].y=Vectex[1].y;
    46
    47 if(!IsConvexBag(Vectex))
    48 cout<<"HOLE IS ILL-FORMED"<<endl;
    49 else
    50 {
    51 bool flag1=IsIn(Vectex);
    52 bool flag2=IsFit(Vectex);
    53
    54 if(flag1 && flag2)
    55 cout<<"PEG WILL FIT"<<endl;
    56 else
    57 cout<<"PEG WILL NOT FIT"<<endl;
    58 }
    59
    60 delete Vectex;
    61 }
    62 return 0;
    63 }
    64
    65 /*精度讨论*/
    66 int precision(double x)
    67 {
    68 if(fabs(x)<=eps)
    69 return 0;
    70 return x>0?1:-1;
    71 }
    72
    73 /*计算点积*/
    74 double dotdet(double x1,double y1,double x2,double y2)
    75 {
    76 return x1*x2+y1*y2;
    77 }
    78
    79 /*计算叉积*/
    80 double det(double x1,double y1,double x2,double y2)
    81 {
    82 return x1*y2-x2*y1;
    83 }
    84 double cross(pos A,pos B,pos C,pos D)
    85 {
    86 return det(B.x-A.x , B.y-A.y , D.x-C.x , D.y-C.y);
    87 }
    88
    89 /*计算距离*/
    90 double distant(pos A,pos B)
    91 {
    92 return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
    93 }
    94
    95 /*计算角度*/
    96 double angle(pos A,pos B,pos P)
    97 {
    98 return acos(dotdet(A.x-P.x,A.y-P.y,B.x-P.x,B.y-P.y)/(distant(A,P)*distant(B,P)));
    99 }
    100
    101 /*凸包判断*/
    102 bool IsConvexBag(pos* Vectex)
    103 {
    104 int direction=0;
    105 //保存点集Vectex的旋转方向direction 1:右手正螺旋,逆时针 -1:左手正螺旋,顺时针
    106 for(int i=0;i<=n-1;i++)
    107 {
    108 int temp=precision(cross(Vectex[i],Vectex[i+1],Vectex[i+1],Vectex[i+2]));
    109
    110 if(!direction) //避免最初的点出现共线的情况
    111 direction=temp;
    112
    113 if(direction*temp<0) //只要Vectex是凸包,那么无论Vectex的旋转方向如何,direction*temp都会>=0
    114 return false;
    115 }
    116 return true;
    117 }
    118
    119 /*判断点与多边形的关系*/
    120 bool IsIn(pos* Vectex)
    121 {
    122 double CircleAngle=0.0; //环绕角
    123 for(int i=1;i<=n;i++) //注意重复边不计算
    124 if(precision(cross(Peg,Vectex[i],Peg,Vectex[i+1]))>=0)
    125 CircleAngle+=angle(Vectex[i],Vectex[i+1],Peg);
    126 else
    127 CircleAngle-=angle(Vectex[i],Vectex[i+1],Peg);
    128
    129 if(precision(CircleAngle)==0) //CircleAngle=0, Peg在多边形外部
    130 return false;
    131 else if(precision(CircleAngle-pi)==0 || precision(CircleAngle+pi)==0) //CircleAngle=180, Peg在多边形边上(不包括顶点)
    132 {
    133 if(precision(PegR)==0)
    134 return true;
    135 }
    136 else if(precision(CircleAngle-2*pi)==0 || precision(CircleAngle+2*pi)==0) //CircleAngle=360, Peg在多边形边内部
    137 return true;
    138 else //CircleAngle=(0,360)之间的任意角, Peg在多边形顶点上
    139 {
    140 if(precision(PegR)==0)
    141 return true;
    142 }
    143 return false;
    144 }
    145
    146 /*判断圆与多边形的关系*/
    147 bool IsFit(pos* Vectex)
    148 {
    149 for(int i=0;i<=n;i++)
    150 {
    151 int k=precision(fabs(cross(Peg,Vectex[i],Peg,Vectex[i+1])/distant(Vectex[i],Vectex[i+1]))-PegR);
    152 if(k<0)
    153 return false;
    154 }
    155
    156 return true;
    157 }

     

     

     

    Sample Input

    5 1.5 1.5 2.0
    1.0 1.0
    2.0 2.0
    1.75 2.0
    1.0 3.0
    0.0 2.0
    5 1.5 1.5 2.0
    1.0 1.0
    2.0 2.0
    1.75 2.5
    1.0 3.0
    0.0 2.0
    3  0.1  0.2 0.0
    -0.5 1.0
    0.5 -1.0
    0.5 1.0
    3  0.25  0.2 0.0
    -0.5 1.0
    0.5 -1.0
    0.5 1.0
    3 0.1 1.6 1.2
    1.0 1.0
    2.0 1.0
    1.0 2.0
    6 0.1 1.6 1.2
    1.0 1.0
    1.5 1.0
    2.0 1.0
    1.2 1.8
    1.0 2.0
    1.0 1.5
    3 0.1 2.0 2.0
    1.0 1.0
    2.0 1.0
    1.0 2.0
    4  1.0  2.0 1.0
    0.0 0.0
    0.0 4.0
    4.0 4.0
    4.0 0.0
    4  1.0  3.5 1.0
    0.0 0.0
    0.0 4.0
    4.0 4.0
    4.0 0.0
    4  0.2  1.5 1.0
    1.0 1.0
    2.0 2.0
    1.0 3.0
    0.0 2.0
    4  0.4  1.5 1.0
    1.0 1.0
    2.0 2.0
    1.0 3.0
    0.0 2.0
    5  0.2  1.5 2.5
    1.0 1.0
    2.0 2.0
    1.75 2.75
    1.0 3.0
    0.0 2.0
    5  0.2  1.5 2.5
    1.0 1.0
    2.0 2.0
    1.75 2.5
    1.0 3.0
    0.0 2.0
    9 0.2 0.5 2.5
    0.0 0.0
    1.0 0.0
    1.0 1.0
    2.0 1.0
    2.0 0.0
    3.0 0.0
    3.0 5.0
    1.5 5.0
    0.0 5.0
    9 0.2 0.5 2.5
    0.0 0.0
    1.0 0.0
    1.0 -1.0
    2.0 -1.0
    2.0 0.0
    3.0 0.0
    3.0 5.0
    1.5 5.0
    0.0 5.0
    7 0.2 0.5 2.5
    0.0 0.0
    1.0 0.0
    2.0 0.0
    3.0 0.0
    3.0 5.0
    1.5 5.0
    0.0 5.0
    4 0.1 1 0.5
    0 2
    1 0
    2 2
    1 1
    1

     

    Sample Output

    HOLE IS ILL-FORMED
    PEG WILL NOT FIT
    PEG WILL FIT
    PEG WILL NOT FIT
    PEG WILL FIT
    PEG WILL FIT
    PEG WILL NOT FIT
    PEG WILL FIT
    PEG WILL NOT FIT
    PEG WILL NOT FIT
    PEG WILL NOT FIT
    PEG WILL FIT
    PEG WILL NOT FIT
    HOLE IS ILL-FORMED
    HOLE IS ILL-FORMED
    PEG WILL FIT
    HOLE IS ILL-FORMED
    [ EXP技术分享博客 ] 版权所有,转载请注明出处: http://exp-blog.com
  • 相关阅读:
    R语言大小写字母转换
    SparkR(R on Spark)编程指南 含 dataframe操作
    SparkR(R on Spark)编程指南 含 dataframe操作
    R-table和tapply函数
    r table
    多变量频率统计——r
    R语言-查看加载包、卸除加载包及安装包与卸载包
    flask 电子邮件进阶实践-用模板发送163邮件 --
    flask 电子邮件Flask-Mail --
    数据库进阶实践-事件监听 --
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2122829.html
Copyright © 2011-2022 走看看