POJ1584:计算几何

POJ1584

题解

  • 首先要判断多边形使否是凸边形。对于连续的点a、b、c,就要判断ab×bc是否都是同号。
  • 其次要判断圆心是否在多边形的内部,因为是凸边形,所以很好判断。对于连续的点a,b,c和圆心o,判断ba×bo和bc×bo的符号。如果存在同号,那么就是在外部。
  • 最后就是判断圆心到边的距离和半径的关系了。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
int const N = 1000 + 10;
double eps = 1e-10;
double r,x,y;
int n;
typedef struct Point{   //点和向量
	double x,y;
	Point(){};
	Point(double x,double y):x(x),y(y){};
	Point operator - (const Point& e)const{   //减
		return Point(x - e.x,y - e.y);
	}
	double operator ^ (const Point& e)const{  //叉乘
		return x * e.y - y * e.x;
	}
	double operator * (const Point& e)const{  //点积
		return x * e.x + y * e.y;
	}
}Vector;
struct Line{    //直线的定义
	Point a,b;
	Line(){};
	Line(Point a,Point b):a(a),b(b){}
};
Point p[N],o;
int dcmp(double x){    //判断符号
	if(fabs(x) < eps)	return 0;
	else return x < 0 ? -1 : 1;
}
double length(Line line){   //线段的长度
	return sqrt(pow(line.a.x - line.b.x,2) + pow(line.a.y - line.b.y,2));
}
double distance(Point p,Line line){   //点到直线距离
	return fabs(((line.b - line.a) ^ (p - line.a)) / length(line));
}
bool formed(){  //判断是否是凸包
	int flag;
	for(int i=0;i<n;i++){
		int j = (i + 1) % n,	k = (i + 2) % n;	
		if(i == 0)	flag = dcmp((p[j] - p[i]) ^ (p[k] - p[j]));
		else if(flag * dcmp((p[j] - p[i]) ^ (p[k] - p[j])) < 0)	return false;
	}
	return true;
}
bool fit(){
	for(int i=0;i<n;i++){
		int j = (i - 1 + n) % n,	k = (i + 1) % n;
		if(dcmp((p[j] - p[i]) ^ (o - p[i])) * dcmp((p[k] - p[i]) ^ (o - p[i])) >= 0)	return false;
		double dis = distance(o,Line(p[i],p[k]));
		if(dcmp(r - dis) > 0)	return false;
	}
	return true;
}
int main(){
	while(~scanf("%d",&n) && n >= 3){
		scanf("%lf%lf%lf",&r,&x,&y);
		o = Point(x,y);
		for(int i=0;i<n;i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		if(formed()){
			if(fit())	printf("PEG WILL FIT\n");
			else	printf("PEG WILL NOT FIT\n");
		}else	printf("HOLE IS ILL-FORMED\n");
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值