Post

[백준] 17387번: 선분 교차 2

[백준] 17387번: 선분 교차 2

📌 문제

https://www.acmicpc.net/problem/17387

📌 설명

CCW 알고리즘을 통해 해결했다.

네 점 A, B, C, D가 있고 선분 AB, 선분 CD의 교차 여부를 판단한다고 할 때, 선분 위의 두 점과 다른 선분의 나머지 한 점의 외적 값을 사용했다. 구체적으로 설명하자면 다음과 같다.

ccw()는 세 점의 외적을 구하는 함수이다. ccw(A, B, C) * ccw(A, B, D) <=0라는 것은 선분 AB를 기준으로 점 C와 점 D가 다른 영역에 존재한다는 것이다. 즉, 교차한다. 그러나 이 조건만으로는 약하므로 선분 CD를 기준으로 점 A와 점 B가 다른 영역에 존재하는지도 확인해야 한다.

추가로 고려해야 할 점은, 모든 ccw 값이 0이라면 두 선분에 포개져있거나 그렇지 않다는 것이다. 따라서 포개져있는지 여부를 확인해주어야 한다. 이는 각 점의 순서를 적절히 바꾸어주고 포개지기 위한 조건을 작성하였다. 이 과정에서 구조체 연산자 오버로딩을 사용하였다.

까다로웠던 점은 ccw의 곱이 매우 커질 수 있기 때문에 long long이 아닌 double형으로 선언되어야 하는 점이었다.

문제를 해결하며 CCW 알고리즘에 대해 알게 되었다. 또한 평소에 구조체를 잘 선언하며 문제를 해결하지 않았는데, 이번 기회를 통해 구조체의 사용과 연산자 오버로딩 설정에 대해 알게 되었다.

📌 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <algorithm>

using namespace std;

struct coor {
	long long x, y;

	bool operator<=(const coor& P)const {
		if (x != P.x)
			return x <= P.x;
		return y <= P.y;
	}
	bool operator>=(const coor& P)const {
		if (x != P.x)
			return x >= P.x;
		return y >= P.y;
	}
};

double ccw(coor A,coor B,coor C) {
	return (B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y);
}

int main() {
	coor A, B, C, D;
	cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> D.x >> D.y;

	// 선분 AB와 선분 CD에서 A와 C는 각각 B와 D보다 x 또는 y 좌표가 작도록 설정
	if (A >= B) {
		swap(A, B);
	}
	if (C >= D) {
		swap(C, D);
	}

	if (ccw(A, B, C) * ccw(A, B, D) <= 0 && ccw(C, D, A) * ccw(C, D, B) <= 0) {
		if (ccw(A, B, C) * ccw(A, B, D) == 0 && ccw(C, D, A) * ccw(C, D, B) == 0) {
			cout << (A <= D && C <= B);
		}
		else
			cout << 1;
	}
	else
		cout << 0;
}
This post is licensed under CC BY 4.0 by the author.