hdu 1086 很基本的计算几何

来源:互联网 发布:隐藏图标的软件 编辑:程序博客网 时间:2024/06/06 09:59

   题意不说,已经很明了,这里主要是用了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 100using 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;}

原创粉丝点击