1041线段相交

做题小结

题目

线段相交
时间限制 (普通/Java):1000MS/3000MS          运行内存限制 :65536KByte
总提交 :356            测试通过 :77
描述


你将判断给定线段 L1L2 是否相交 , 其中L1 表示为s1x,s1y,e1x,e1y L2表示为s2x,s2y,e2x,e2y

输入


多组数据输入,每组一行,每组八个浮点数, s1x,s1y,e1x,e1y,s2x,s2y,e2x,e2y

输出


相交则输出 yes否则输出no

样例输入

0 1 2 1 1 0 1 2
1 1 2 2 3 3 4 4

样例输出

yes
no

算法

这一类的几何题目,可以先想象满足题目条件有哪几种情况。例如这道题目说的是线段相交,其实在一个二维平面上,线段相交就只有如下三种情况:




线段相交有三种可能性:
1)两个线段的四个点均分布在另外一条线段的两端;
2)一个线段的某一个端点在另一条线段上;
3)两个线段重合,一个长一个短;
显然,我们需要判断一个点在一条线段的左边,右边,还是正好在上边。这里就需要一个函数,返回就是点和线段的位置关系。

具体而言,对于情况 1)我们需要分别判断Line1的两点是否在 Line2的两边,以及Line2的两点是否在 Line1的两边;
对于情况 2)我们需要判断一个点是否在另一个线段上;情况 3)我们需要判断两个线段共线,然后一个线段的两点均在另一个线段的内部,也就是 x坐标位于之间。

代码如下:
#include<iostream>
using namespace std;

int RightOrLeft(double sX, double sY, double L1X, double L1Y, double L2X, double L2Y)
{
         double difference=(sX-L1X)*(L2Y-L1Y)-(sY-L1Y)*(L2X-L1X);
         if (difference>0)
                   return 1;
         if(difference<0)
                   return -1;
         if(difference==0)
         {
                   if( (sX<L1X&&sX<L2X) || (sX>L1X&&sX>L2X))  //co-line yet not inside
                            return 0;
                   else
                            return 100;  //inside the line segment
         }
         return 100000;
}

int main()
{
         double fir1X, fir1Y, fir2X, fir2Y;
         double sec1X, sec1Y, sec2X, sec2Y;

//      int flag1, flag2;
//      freopen("test.txt", "r", stdin);
         while(cin>>fir1X>>fir1Y>>fir2X>>fir2Y>>sec1X>>sec1Y>>sec2X>>sec2Y)
         {
                   int flag1=RightOrLeft(sec1X, sec1Y, fir1X, fir1Y, fir2X, fir2Y);
                   int flag2=RightOrLeft(sec2X, sec2Y, fir1X, fir1Y, fir2X, fir2Y);
                   int flag3=RightOrLeft(fir1X, fir1Y, sec1X, sec1Y, sec2X, sec2Y);
                   int flag4=RightOrLeft(fir2X, fir2Y, sec1X, sec1Y, sec2X, sec2Y);

//               cout<<flag1<<' '<<flag2<<' '<<flag3<<' '<<flag4<<endl;

                   if(flag1==100
                            ||flag2==100
                            ||flag3==100
                            ||flag4==100)  //exist one point in the line segment
                   {
                            cout<<"yes"<<endl;
                            continue;
                   }

                   if( (flag1*flag2<0) && (flag3*flag4<0) )
                   {
                            cout<<"yes"<<endl;
                            continue;
                   }

                   if(flag1+flag2==0
                            && flag3+flag4==0)
                   {
                            if( (fir1X<sec1X&&fir1X<sec2X&&fir2X>sec1X&&fir2X>sec2X)
                                     ||(sec1X<fir1X&&sec1X<fir2X&&sec2X>fir1X&&sec2X>fir2X) )
                            {
                                     cout<<"yes"<<endl;
                                     continue;
                            }
                   }

                   cout<<"no"<<endl;

         }

         return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值