두 선분이 주어질 때 선분이 교차하는지 판별하는 방법을 알아보겠습니다

 

선분 AB, CD 가 다음과 같이 있다고 가정하겠습니다

이 때 선분 AB, CD 가 교차하는지 확인하는 방법은

삼각형의 면적을 구하는 공식+벡터 를 통해서 결정할 수 있습니다

 

이를 구하는 함수는 보통 CCW (반시계방향의 줄임말) 으로 세점에 대한 방향성을 확인하는 함수라 칭하겠습니다

삼각형의 면적 + 벡터를 구하는 공식은 다음과 같습니다

1, 2, 3 을 각각 함수의 인자로 받게될 선분의 정점이라고 가정한다면

다음과 같은 함수를 만들 수 있습니다.

1
2
3
4
5
6
7
8
9
10
typedef struct {
    int x, y;
}pii;
 
int ccw(pii a, pii b, pii c) {
    int ans = (b.x - a.x) * (c.y - a.y) - (b.y - a.y)* (c.x - a.x);
    if (ans < 0return 1;
    else if (ans > 0return -1;
    else return 0;
}
 

 

위의 그림에서 선분 AB로 선분CD를 확인하는 CCW는 다음과 같이 호출할 수 있습니다

CCW(A,B,C), CCW(A,B,D) 

CCW(A,B,C) 의 의미는 선분 AB 에 대한 정점 C 의 방향을 벡터로 반환받는다는 의미입니다

이 때 CCW(A,B,C) * CCW(A,B,D) 의 곱이 음수이면, 즉 각 함수의 반환값이 0이 아닌 음수와 양수이면

두 선분은 교차하는 것으로 판별할 수 있습니다.

만약 값이 0 이라면 두 선분은 평행하다는 의미입니다.

 

지금까지의 설명은 임의의 볼록다각형에서 사용할 수 있는 방법입니다.

다시 정의하자면, 어떤 주어진 볼록다각형의 그 선 위에 있는 좌표끼리로만 판단할 수 있다는 의미입니다.

 

다음 설명할 것은 볼록다각형이 아닌 좌표평면에 대한 두 선분의 교차를 판별하는 방법입니다.

정해진 선 위에서 존재하는 정점이 아니라면 다음과 같은 경우가 있을 수 있습니다.

선분AB 에 대해서 선분CD 에 대한 CCW 를 구하게 되면 분명 그 곱은 음수가 될 것입니다.

교차한다는 의미가 됩니다.

하지만 육안으로 보면 두 선분은 교차하지 않고 있습니다.

어떻게 교차하는지 확인할 수 있을까요?

 

그 방법은 두 선분에 대한 CCW를 모두 구해주는 것입니다.

선분AB 에 대한 선분CD, 선분 CD에 대한 선분 AB 이 될 것입니다.

그리고 다음과 같은 조건에 의해 두 선분이 교차한다고 할 수 있습니다.

CCW(A,B,C)*CCW(A,B,D) <=0 && CCW(C,D,A)*CCW(C,D,B) <=0

 

이 식에는 다음과 같은 반례가 존재합니다.

다음과 같은 경우 두선분 각각 CCW 를 구했을 때 둘다 0이라는 값을 가지게 됩니다.

이때는 위와 같은 상태인지, 아래와 같은 상태인지 알 수 없게 됩니다.

이럴 때 두 선분이 교차하는지 확인하는 방법은 정점의 상대적인 위치를 확인해주는 것입니다.

B가 C 보다 크거나 같고 A 가 D 보다 작거나 같으면 두 선분은 교차하게 됩니다.

A<=D && B>=C

'algorithm > algorithm' 카테고리의 다른 글

볼록껍질 선분 처리하기  (0) 2020.02.28
유클리드 호제법  (0) 2020.02.28
세그먼트 트리 정리  (0) 2020.02.05
삼분 탐색(Ternary search)  (0) 2020.01.16
LCS  (0) 2019.07.04

아직은 기본기만 사용할 줄 알고 특정한 경우에 대한 반례들이 있어 (ex: 평평한 구간에 최솟값, ..)

삼분 탐색을 알고 있다고 말하기는 힘들지만 이해할려고 노력했기 때문에 조심스럽게 글을 써봅니다

 

https://m.blog.naver.com/PostView.nhn?blogId=kks227&logNo=221432986308&proxyReferer=https%3A%2F%2Fwww.google.com%2F

삼분탐색에 대한 공부는 여기서 했으며 정리를 매우 잘해놓으셨으니 제 포스트 보다는 여길 참고하시는게 좋습니다.

 

삼분탐색은 이분탐색과 같은 원하는 값을 위한 증감 범위를 이용한 탐색인데

이분탐색은 정렬이 되어있기 때문에 반드시 임의의 값을 기준으로 한군데는 증가한다면 반대는 감소하는 형식입니다.

말그대로 일차방정식의 직선과 같은 그림을 상상해볼 수 있습니다.

 

반대로 삼분탐색은 어떤 원하는 값들의 형태가 직선형태의 무조건적인 증감을 말하는게 아닌

아래나 위로 볼록한 형태의 특성을 띄는 값들 중에서 원하는 값을 찾기 위해 사용할 수 있는 탐색방법 입니다.

이 탐색방법을 이용하여 이분탐색보다 구체화(?) 된 조건으로 이 볼록한 구간내의 원하는 값을 탐색해나갈 수 있습니다.

이해를 위해 그림으로 설명해보면, 

 

 

이와 같이 표현할 수 있고, 이 볼록한 구간을 이용하기 위해

fp, lp 그리고 삼등분한 p1, p2 를 구하게 된다면

p1 과 p2 를 이용하여 이 곡선(방정식)에 대한 함수값을 구할 수 있게 됩니다.

 

곡선의 식을 Func 라고할때

Func(p1) 의 값이 Func(p2) 보다 작은 경우 알 수 있는 사실은

구간 [p2,lp] 에 존재하는 최소값은 구간 [fp,p2] 에 존재하는 최소값보다 작을 수 없다 입니다.

=> 만약 볼록 구간 중에서 최소값을 찾고자 한다면 구간 [fp,p2] 의 범위를 탐색해야한다 는 뜻입니다.

 

이를 이용하여 fp 와 lp 를 원하는 조건에 맞게 p1 p2 값으로 바꾸어주면서 탐색하는 방법이 삼분 탐색입니다.

 

삼분탐색을 이용한 문제는

BOJ : https://www.acmicpc.net/problem/11662 민호와 강호

BOJ : https://www.acmicpc.net/problem/13310 먼 별

BOJ : https://www.acmicpc.net/problem/8986 전봇대 

등이 있으며

민호와 강호 문제가 삼분탐색을 이용한 문제 중에 제일 기초? 문제 인듯 싶으니 풀어보시면 좋을 것 같습니다.

(삼분탐색으로 안해도 해결가능합니다!)

 

삼분 탐색을 설명했는데 미흡한 부분이나 틀린 부분이 있다면 지적부탁드립니다!

'algorithm > algorithm' 카테고리의 다른 글

볼록껍질 선분 처리하기  (0) 2020.02.28
유클리드 호제법  (0) 2020.02.28
세그먼트 트리 정리  (0) 2020.02.05
선분 교차 판별하기  (0) 2020.02.02
LCS  (0) 2019.07.04

LCS(longest common sequence) - 공통되는 최장 부분수열

 

string f = ACAYKP

string s = CACANK

 

이렇게 두 문자열이 있다면 공통되는 최대 길이의 부분수열은 A C A K -> 4 가 된다.

LCS 는 DP 를 통해서 구현되며

LCS4 번 문제같은 조건이 주어진 숫자의 경우 lis 알고리즘으로 해결한다.

(나중에 공부하고 포스팅해야지)

 

기본적으로 두 문자열에 대한 dp[][] 를 선언으로 시작한다.

한 문자열에 대해서 다른 문자열의 각 문자를 전부 비교한다.

 

f[i] == s[k] 이면 dp[i][k] = dp[i-1][k-1]+1;

f[i] != s[k] 이면 dp[i][k] = max(dp[i-1][k], dp[i][k-1]);

 

************************************************************************

부분수열이 아닌 문자열을 찾는 것이라면

f[i] == s[k] 이면 dp[i][k] = dp[i-1][k-1]+1;

위 점화식을 이용하여 공통된 문자열의 최대 길이를 찾을 수 있다.

ex)

ACACK

CACIP

--> CAC : 3

************************************************************************

'algorithm > algorithm' 카테고리의 다른 글

볼록껍질 선분 처리하기  (0) 2020.02.28
유클리드 호제법  (0) 2020.02.28
세그먼트 트리 정리  (0) 2020.02.05
선분 교차 판별하기  (0) 2020.02.02
삼분 탐색(Ternary search)  (0) 2020.01.16

+ Recent posts