poj1127(计算几何线段相交判断,模板)

解题思路:关于计算几何部分详见下面代码的注释,以及挑战p253。这道题可以拿出来做模板的地方on_seg,用于判断一个点是否在直线上。和intersection求交点部分,但是不能处理两条直线平行的情况,需要提前判断两条线是否平行。最后用了floyd算法来进行相连拓展。其实这里证明floyd可行性是一个比较复杂的过程,但是我们可以联想前面求最短路的时候,

dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]),这说明是正则的,最后的结果可以收敛。更简单的说和这次用到的形式一样,所以可以套用。

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-10;
int n;
double add(double a,double b)
{
    if(abs(a+b)<eps*(abs(a)+abs(b)))  return 0;
    return a+b;
}
struct node
{
	double x,y;
	node(){
	}
	node(double x,double y):x(x),y(y){
	}
	node operator+(node p)
	{
		return node(add(x,p.x),add(y,p.y));
	}
	node operator-(node p)
	{
		return node(add(x,-p.x),add(y,-p.y));
	}
	node operator*(double d)
	{
		return(node(d*x,d*y));
	}
	double dot(node p)
	{
		return add(x*p.x,y*p.y);
	}
	double det(node p)
	{
		return add(x*p.y,-y*p.x);
	} 
};
node p[20],q[20];
bool g[40][40]; 
int on_seg(node p,node q,node r)//这一段处理很不错,判断坐标r在不在线段p-q上 
{
	if(((p-r).det(q-r))==0 && (p-r).dot(q-r)<=0)
	return 1;
	return 0;
}
node intersection(node p1,node p2,node q1,node q2)//计算p1-p2和q1-q2直线交点 
{
	return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));//这种计算方法挺不错,可以处理斜率不存在的情况! 
}
void solve()
{
	memset(g,0,sizeof(g));
	for(int i=0;i<n;i++)
	{
		g[i][i]=1;
		for(int j=0;j<i;j++)
		{
			if((p[i]-q[i]).det(p[j]-q[j])==0)//相交公式算不了平行时的情况 
			{//平行		 
				g[i][j]=g[j][i]=on_seg(p[i],q[i],p[j])
					||on_seg(p[i],q[i],q[j])
					||on_seg(p[j],q[j],p[i])
					||on_seg(p[j],q[j],q[i]);
			}else
			{
				node tp=intersection(p[i],q[i],p[j],q[j]);
				//if(i==3&&j==0) printf("%(%lf %lf) %lf %lf*\n",p[i].x,p[i].y,tp.x,tp.y);
				g[i][j]=g[j][i]=on_seg(p[i],q[i],tp)&&on_seg(p[j],q[j],tp);
			}
		}
	}
	for(int k=0;k<n;k++)
	{
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				g[i][j] |= g[i][k]&&g[k][j];
			}
		}
    }
}
int main()
{
	//freopen("t.txt","r",stdin);
	int a,b;
	while(~scanf("%d",&n)&&n)
	{
		for(int i=0;i<n;i++)
		{
			scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y);		
		}
		solve();
		while(~scanf("%d%d",&a,&b))
		{
			if(a==0&&b==0) break;
			if(g[a-1][b-1])
			printf("CONNECTED\n");
			else
			printf("NOT CONNECTED\n");
		}
	}
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/qq_39861441/article/details/87715422
今日推荐