0
题目:
询问给出的多边形是凸多边形还是凹多边形(两者区别: if there exist any two interior points in the hole that, if connected by a line segment, that segment would cross one or more edges of the hole,如果存在有任意两个顶点的连线会经过边的情况则是凹多边形,凸多边形任意两个顶点连线都是在多边形内部)
给出一个peg,去填补给出的多边形,要求peg的坐标在多边形内且半径小于等于到多边形任意边的距离。
1
分析:
凸包判断,求连续两个边的向量的叉乘,如果方向(正负)出现不同,说明不是凸包。
点和多边形位置关系判断,用点和连续的两个多边形的顶点相连得到的向量叉乘,如果出现方向(正负)改变说明点在多边形外面。
(其他作法,大同小异,原理是一样的,如这里)
优势:代码要规范简洁,如果给出的顺序是顺时针则调用reserve函数翻转点的顺序使按顺序叉乘符号>0使后面程序书写更方便,dblcmp函数减少精度问题,struct的使用以及重载符号,xmult叉乘函数拿出。
2
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <string>
#include <math.h>
#include <algorithm>
//是否是凸多边形,钉子位置是否在多边形内,钉子的半径是否大于到每一条边的距离
//如果是bool 函数,return false ,return true.那么主函数里一定要是 if(!函数名),而不是if(函数名==-1),因为false==0!!!
using namespace std;
const double eps=1e-8;
const int maxn=110;
struct points{
double x;
double y;
double len(){
return sqrt(x*x+y*y+eps);
}
points operator - (const points & a){
points next;
next.x=x-a.x;
next.y=y-a.y;
return next;
}
}point[maxn],peg;
int n;double pr;double px,py;
double xmult(points vec1,points vec2){
return vec1.x*vec2.y-vec1.y*vec2.x;
}
int dblcmp(double x){
if(fabs(x)<eps) return 0;
else{
return x>0?1:-1;
}
}
bool Convex(){///判断是否是凸包
for(int i=0;i<n;i++){
if(dblcmp(xmult(point[(i+1)%n]-point[i],point[(i+2)%n]-point[(i+1)%n]))<0){//==0就是点共线不能说明不是凸多边形所以不判
return false;
}
}
return true;
}
double lenth(points p){
return p.len();
}
bool Inconvex_Infit(){///对于点和多边形的位置关系:double pos=xmult(point[i%n]-peg,point[(i+1)%n]-peg);只要出现一次pos<0:点在多边形外部;只要出现一次pos==0,点在多边形的边上;如果pos>0总是成立,点在多边形外部
for(int i=0;i<n;i++){
if(xmult(point[i%n]-peg,point[(i+1)%n]-peg)<=0){//点是否在多边形内
if(xmult(point[i%n]-peg,point[(i+1)%n]-peg)==0&&pr==0){//如果钉子在多边形的边上且钉子的面积近乎为0也是可以插入的,不过实际情况中几乎不存在,题目中也没有考到这个数据
return true;
}
return false;
}
if(dblcmp(xmult(point[i%n]-peg,point[(i+1)%n]-peg)/fabs(lenth(point[(i+1)%n]-point[i%n]))-pr)<0){//大小是否能覆盖
return false;
}
}
return true;
}
int main(){
while(~scanf("%d",&n)&&n>=3){
///ini
scanf("%lf%lf%lf",&pr,&peg.x,&peg.y);
for(int i=0;i<n;i++){
scanf("%lf%lf",&point[i].x,&point[i].y);
}
///reverse
double temparea=0;
int u=0;
while(temparea==0&&u<n){
temparea=dblcmp(xmult(point[(u+1)%n]-point[u],point[(u+2)%n]-point[u]));
u++;
}
if(temparea<0){
reverse(point,point+n);
}
///judge
if(Convex()==0){
cout<<"HOLE IS ILL-FORMED"<<endl;
continue;
}
if(!Inconvex_Infit()){
cout<<"PEG WILL NOT FIT"<<endl;
}
else{
cout<<"PEG WILL FIT"<<endl;
}
}
}