알고리즘/코테
[백준 17387] 선분 교차 2
kiwiiiv
2022. 3. 11. 23:44
https://www.acmicpc.net/problem/17387
17387번: 선분 교차 2
첫째 줄에 L1의 양 끝 점 x1, y1, x2, y2가, 둘째 줄에 L2의 양 끝 점 x3, y3, x4, y4가 주어진다.
www.acmicpc.net
진짜진짜 금방 풀 줄 알았는데..
"세 점은 평행하지 않는다" 란 조건 하나가 빠지니까 신경써야 할 경우의 수들이 우수수.. 나오더라?
여튼 1 버전에 비교해서 추가된 상황을 생각하여 보면
1. 한 선분이 다른 선분을 포함함
ex)
1 1 5 5
5 5 1 1
1 1 5 5
3 3 4 4
2. 두 점이 겹침
ex)
1 1 5 5
5 5 9 9
1 1 5 5
5 5 1 5
3. 한 점이 다른 선분 안에 있음
ex)
1 1 5 5
3 3 1 3
위처럼 추가된 경우로 인해,
ccw을 이용하여 선분의 교차 여부를 판단하는 방법이 복잡해졌다.
점의 일치 여부를 판단하고 선분의 평행 여부를 판단하고 또 그 평행한 선분이 다른 선분에 포함되는 지를 판단하고..
따라서 다음과 같이 코드를 작성했다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
class Main {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
double segment[] = new double[4];
double segment2[] = new double[4];
String line = br.readLine();
segment = Arrays.stream(line.split(" ")).mapToDouble(Double::parseDouble).toArray();
double dotA[] = Arrays.copyOfRange(segment, 0, 2);
double dotB[] = Arrays.copyOfRange(segment, 2, segment.length);
line = br.readLine();
segment = Arrays.stream(line.split(" ")).mapToDouble(Double::parseDouble).toArray();
double dotC[] = Arrays.copyOfRange(segment, 0, 2);
double dotD[] = Arrays.copyOfRange(segment, 2, segment.length);
if (isCross(dotA, dotB, dotC, dotD)) {
System.out.println(1);
} else {
System.out.println(0);
}
}
private static boolean isCross(double a[], double b[], double c[], double d[]) {
//겹치는 점
if (Arrays.equals(a, c) || Arrays.equals(a, d) || Arrays.equals(b, c) || Arrays.equals(b, d)) {
return true;
}
boolean flatFlag = false;
int sum1;
int sumA, sumB;
sumA = ccw(a, b, c);
sumB = ccw(a, b, d);
sum1 = sumA * sumB;
if (sumA == 0 && sumB == 0) flatFlag = true;
int sum2;
sumA = ccw(c, d, a);
sumB = ccw(c, d, b);
sum2 = sumA * sumB;
//평행 선분 판별
if (sumA == 0 && sumB == 0 && flatFlag == true) flatFlag = true;
else flatFlag = false;
if (sum1 == 1 || sum2 == 1 ) {
return false;
}else if(flatFlag ==true){ //평행
if ((between(a, b, c) || between(a, b, d)) || (between(c, d, a) || between(c, d, b))) { //포함
return true;
} else {
return false;
}
} else {
return true;
}
}
private static int ccw(double a[], double b[], double c[]) {
double ans;
ans = (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
if(ans==0) return 0;
else if(ans>0) return 1;
else return -1;
}
//ab에 대한 c의 포함 여부
private static boolean between(double a[], double b[], double c[]) {
double lL[] = (a[0] < b[0]) ? a : b;
double lR[] = (a[0] > b[0]) ? a : b;
if(c[0]>=lL[0] && c[0]<lR[0])
return true;
else
return false;
}
}