ACM模版

描述

给出平面上两条线段的两个端点,判断这两条线段是否相交(有一个公共点或有部分重合认为相交)。 如果相交,输出”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

题解

计算几何相关问题。

代码

#include <iostream>

using namespace std;

const double eps = 1e-10;

struct point
{
    double x, y;
};

double min(double a, double b)
{
    return a < b ? a : b;
}

double max(double a, double b)
{
    return a > b ? a : b;
}

bool inter(point a, point b, point c, point d)
{
    if (min(a.x, b.x) > max(c.x, d.x) || min(a.y, b.y) > max(c.y, d.y) || min(c.x, d.x) > max(a.x, b.x) || min(c.y, d.y) > max(a.y, b.y))
    {
        return 0;
    }
    double h, i, j, k;
    h = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    i = (b.x - a.x) * (d.y - a.y) - (b.y - a.y) * (d.x - a.x);
    j = (d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x);
    k = (d.x - c.x) * (b.y - c.y) - (d.y - c.y) * (b.x - c.x);
    return h * i <= eps && j * k <= eps;
}

int main(int argc, const char * argv[])
{
#ifndef TEST_DATA
    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    int T;
    cin >> T;
    point a, b, c, d;

    while (T--)
    {
        cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y >> d.x >> d.y;

        if (inter(a, b, c, d))
        {
            cout << "Yes\n";
        }
        else
        {
            cout << "No\n";
        }
    }

    return 0;
}

参考

《判断线段相交》