hdu 1086 很基本的计算几何

   题意不说,已经很明了,这里主要是用了acmppt里面的那个拐向方法判断两条线段是否相交;

先写点基本知识:

           1. 两下向量p1 ,p2 它们的叉乘(不是点乘):

                                p1Xp2 = x1*y2-x2*y1 = -p2Xp1;

                           如果:

                                     p1Xp2 >0 :表示p2在p1的顺时针方向;

                                     p1Xp2 < 0:表示p2在p1的逆时针方向;

                                     p1Xp2 = 0: 表示p1 与 p2共线,方向不定;

        2.判断折线的拐向:



                   再看图:


     我们可用判断折线p2 p1 p3 和 p2 p1 p4的拐向从而知道 点 p4与p3是否分别位于线段p1p2的两边; 同理可以知道点p1 p2 是否在线段p3p4的两边;

如果都成立则线段相交;否则如图当p1,p4,p2共线,只要判断p4是否在点p1 与p2之间就可以了,这很容易;

           判断拐向的代码(判断点c在线段ab的那一边):

                            

double direction(cor& a,cor& b,cor& c){//以判断折线拐向的方法判断C点在线段s1的那边
	double x0 = b.x-a.x;
	double y0 = b.y-a.y;
	double x1 = c.x-a.x;
	double y1 = c.y-a.y;
	return x0*y1-x1*y0;
}
         共线时的情况:

             

bool on_segment(cor& a,cor& b,cor& c){//cout <<a.x <<' '<<a.y << ' '<<b.x <<' ' <<b.y <<' ' <<c.x <<' ' <<c.y <<endl;
	return ((min(a.x,b.x) <= c.x && c.x <= max(a.x,b.x)) 
		    && (min(a.y,a.y) <= c.y,c.y <= max(a.y,b.y)));
}


原代码:

           

#include<iostream>
#include<cmath>

#define N 100
using namespace std;

struct cor{
	double x,y;
};

struct elem{
	cor a;
	cor b;
};

double direction(cor& a,cor& b,cor& c){//以判断折线拐向的方法判断C点在线段s1的那边
	double x0 = b.x-a.x;
	double y0 = b.y-a.y;
	double x1 = c.x-a.x;
	double y1 = c.y-a.y;
	return x0*y1-x1*y0;
}

bool on_segment(cor& a,cor& b,cor& c){//cout <<a.x <<' '<<a.y << ' '<<b.x <<' ' <<b.y <<' ' <<c.x <<' ' <<c.y <<endl;
	return ((min(a.x,b.x) <= c.x && c.x <= max(a.x,b.x)) 
		    && (min(a.y,a.y) <= c.y,c.y <= max(a.y,b.y)));
}

bool judge(elem& s1,elem& s2){
	double d1 = direction(s1.a,s1.b,s2.b);
	double d2 = direction(s1.a,s1.b,s2.a);
	double d3 = direction(s2.a,s2.b,s1.a);
	double d4 = direction(s2.a,s2.b,s1.b);
	if((d1*d2 < 0) && (d3*d4 < 0))
		return true;
	else if(!d1 && on_segment(s1.a,s1.b,s2.b))
		return true;
	else if(!d2 && on_segment(s1.a,s1.b,s2.a))
		return true;
	else if(!d3 && on_segment(s2.a,s2.b,s1.a))
		return true;
	else if(!d4 && on_segment(s2.a,s2.b,s1.b))
		return true;
	else
	    return false;
}

int main()
{
	int nLines;
	int count;
	elem seg[N];
	while(cin >>nLines && nLines){
		count = 0;
		for(int i = 0; i < nLines;i++){
			cin >>seg[i].a.x >>seg[i].a.y >>seg[i].b.x >>seg[i].b.y;
		}
		for(int i = 0; i < nLines;i++){
			for(int j = i+1; j < nLines;j++){
				if(judge(seg[i],seg[j]))
					count++;
			}
		}
		cout <<count <<endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值