【POJ】1584 A Round Peg in a Ground Hole-凸包

本文详细解析了POJ1584题目,介绍了如何通过求凸包和判断点到直线的距离来解决该问题。文章包括了完整的代码实现,涵盖了点的定义、向量运算、点到直线距离的计算以及凸包的判断等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:poj1584


题解

裸的求凸包和判点到直线距离

就是很久不打算几细节会错很多,比如:

inline db ptdis(P a,Line b)
{return fabs((b.st-a)^(b.ed-a))/sqrt(b.dir.sq());}

打成了

inline db ptdis(P a,Line b)
{return fabs((b.st-a)^(b.ed-a))/2/b.dir.sq();}

还有判凸包上同一条边上多条点的兼容也错了

查错令人智熄


代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#define sqr(x) (x*x)
typedef double db;
using namespace std;
const db eps=1e-8;
const int N=1100;

int n;db R;

struct P{
   db x,y;
   P(db x_=0.0,db y_=0.0):x(x_),y(y_){};
   inline P operator +(const P&ky){return P(x+ky.x,y+ky.y);}
   inline P operator -(const P&ky){return P(x-ky.x,y-ky.y);}
   inline db operator ^(const P&ky){return x*ky.y-y*ky.x;}
   inline db sq(){return sqr(x)+sqr(y);}
   bool operator <(const P&ky)const{
   	 db a=atan2(y,x),b=atan2(ky.y,ky.x);
   	 return a!=b?a<b:x<ky.x;
   } 
}p[N],st,ori,ct;

struct Line{
	P st,ed,dir;
	Line(){};
	Line(P st_,P ed_){st=st_;ed=ed_;dir=ed-st;}
};

inline int dcmp(db x){if(fabs(x)<eps) return 0;return x>0?1:-1;}
inline bool onlf(P a,P b,P c){return (dcmp((c-b)^(b-a))>-1);}

//点到直线距离
inline db ptdis(P a,Line b)
{return fabs((b.st-a)^(b.ed-a))/sqrt(b.dir.sq());}

inline bool Convex()
{
	for(int i=1;i<=n;++i)
	 if(dcmp((p[i+1]-p[i])^(p[i+2]-p[i+1]))<0) return false;
	return true;
}

inline bool jud()
{
	int i;db res;
	for(i=1;i<=n;++i){
		res=(p[i]-ct)^(p[i+1]-ct);		
		if((res==0)&&(R==0)) return true;
		if(res<=0 || dcmp(ptdis(ct,Line(p[i],p[i+1]))-R)<0) return false;
    }
    return true;
} 

int main(){
	int i;db area;
	for(;scanf("%d",&n)!=EOF;){
		if(n<3) break;
		scanf("%lf%lf%lf",&R,&ct.x,&ct.y);
		for(i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y);
	    p[n+1]=p[1];p[n+2]=p[2];
		for(area=0,i=1;area==0.0 && i<n;++i)
			area+=(p[i+1]-p[i])^(p[i+2]-p[i]);
		if(area<0) reverse(p+1,p+n+1);p[n+1]=p[1];p[n+2]=p[2];
		if(!Convex()) {puts("HOLE IS ILL-FORMED");continue;}
		puts(jud()?"PEG WILL FIT":"PEG WILL NOT FIT");
	}
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值