1. 程式人生 > >1264 線段相交解題報告(51nod)

1264 線段相交解題報告(51nod)

給出平面上兩條線段的兩個端點,判斷這兩條線段是否相交(有一個公共點或有部分重合認為相交)。 如果相交,輸出"Yes",否則輸出"No"。

Input

第1行:一個數T,表示輸入的測試數量(1 <= T <= 1000)
第2 - T + 1行:每行8個數,x1,y1,x2,y2,x3,y3,x4,y4。(-10^8 <= xi, yi <= 10^8)
(直線1的兩個端點為x1,y1 | x2, y2,直線2的兩個端點為x3,y3 | x4, y4)

Output

輸出共T行,如果相交輸出"Yes",否則輸出"No"。

Input示例

2
1 2 2 1 0 0 2 2
-1 1 1 1 0 0 1 -1

Output示例

Yes
No

我開始時這樣想的 

在圖中,若兩線段相交,這四個向量(a1,a2,a3,a4)會有一定的關係 ,即若相交,則(a1+a2)*(a3+a4)<0-------------結果這種方法不行

其實發現只要四個端點形成的四邊形是凸四邊形(這個該怎麼判斷呢,),則兩線段相交。

別人是用叉積算的:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct Point
{
    double x;
    double y;
};
Point a,b,c,d;
//叉積
double mult(Point a, Point b, Point c)
{
	return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}

//aa, bb為一條線段兩端點 cc, dd為另一條線段的兩端點 相交返回true, 不相交返回false
bool intersect(Point aa, Point bb, Point cc, Point dd)
{
	if ( max(aa.x, bb.x)<min(cc.x, dd.x) )
	{
		return false;
	}
	if ( max(aa.y, bb.y)<min(cc.y, dd.y) )
	{
		return false;
	}
	if ( max(cc.x, dd.x)<min(aa.x, bb.x) )
	{
		return false;
	}
	if ( max(cc.y, dd.y)<min(aa.y, bb.y) )
	{
		return false;
	}
	if ( mult(cc, bb, aa)*mult(bb, dd, aa)<0 )
	{
		return false;
	}
	if ( mult(aa, dd, cc)*mult(dd, bb, cc)<0 )
	{
		return false;
	}
	return true;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&d.x,&d.y);
        if(intersect(a,b,c,d))
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}