(图论)51NOD 1264 线段相交

给出平面上两条线段的两个端点,判断这两条线段是否相交(有一个公共点或有部分重合认为相交)。 如果相交,输出"Yes",否则输出"No"。
 

输入

第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)

输出

输出共T行,如果相交输出"Yes",否则输出"No"。

输入样例

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

输出样例

Yes
No
解:
方法一(函数):
  已知两点,故可以求得两点所在直线方程Ax+By+C=0。
  Ax1+By1=Ax2+By2----->A=k(y2-y1);B=k(x1-x2);C=k(x2y1-x1y2);
  另两点位置不应位于直线同侧(四点共线需特殊判断)。
  将另两点坐标分别带入方程,比较结果与零的关系,可以判断两点与直线的相对位置关系。
  (其实写这道题最大的收获是对于?:运算符的使用有了更多的理解)
 1 #include <stdio.h>
 2 
 3 long long num[8];
 4 int cfun()
 5 {
 6     long long a, b, c, fg1, fg2;
 7     a = num[0] - num[2];
 8     b = num[3] - num[1];
 9     c = num[1] * num[2] - num[0] * num[3];
10     fg1 = a * num[5] + b * num[4] + c > 0 ? 1 : a * num[5] + b * num[4] + c == 0 ? 0 : -1;///
11     fg2 = a * num[7] + b * num[6] + c > 0 ? 1 : a * num[7] + b * num[6] + c == 0 ? 0 : -1;
12     if (fg1 * fg2 > 0) return 0;
13     else if (0 == (fg1 | fg2))//不加这段if判断也可以ac,但其实程序并没有对于四点一线特殊情况的判断。
14     {
15         int max[2], min[2];
16         max[0] = num[0] > num[2] ? (min[0] = num[2], num[0]) : (min[0] = num[0], num[2]);///
17         max[1] = num[4] > num[6] ? (min[1] = num[6], num[4]) : (min[1] = num[4], num[6]);
18         if (max[0] < min[1] || max[1] < min[0]) return 0;
19         else return 1;
20     }
21     a = num[4] - num[6];
22     b = num[7] - num[5];
23     c = num[6] * num[5] - num[4] * num[7];
24     fg1 = a * num[1] + b * num[0] + c > 0 ? 1 : -1;
25     fg2 = a * num[3] + b * num[2] + c > 0 ? 1 : -1;
26     if (fg1 * fg2 > 0) return 0;
27     return 1;
28 }
29 
30 int main()
31 {
32     int t;
33     while (scanf_s("%d", &t) != EOF)
34     {
35         //FILE *fp;
36         //fopen_s(&fp, "a.txt", "w" );
37         while (t--)
38         {
39             scanf_s("%lld%lld%lld%lld%lld%lld%lld%lld", &num[0], &num[1], &num[2], &num[3], &num[4], &num[5], &num[6], &num[7]);
40             fprintf(stdout,"%s\n", cfun() > 0 ? "Yes": "No");
41         }
42         //fclose(fp);
43     }
44     return 0;
45 }

方法二(向量):

  从网上看到的做法,简单的说就是通过两个实验 

  1.快速排斥实验(判断以两点为对角线的矩形的重合情况) 

  2.跨立实验(判断两点连线与另两点的相对位置关系【进行两次】)

  从而得出答案。

其实两种方法殊途同归,从数学的角度可以借此看出一些一次函数和向量的关系。

posted @ 2018-12-01 14:31  Ekalos  阅读(205)  评论(0编辑  收藏  举报