Blog | Tag | Local | Guest | Login | Write |  RSS
안녕하세요 조일룡입니다.

오늘은 원래 비트연산을 이용한 Brute Force Search를 하려고 했는데요..

갑자기 마음이 바껴서 부록으로 터너리서치를 다뤄볼까 합니다.




Ternary Search(터너리 서치)
는 함수의 최대나 최소점을 찾는 알고리즘으로 바이너리서치와 그 동작방법이 비슷합니다.

터너리 서치로 최대점을 찾을 수 있는 함수는 최대점을 기준으로 왼쪽은 단조증가 오른쪽은 단조감소 해야합니다.
마찬가지로 최소점을 찾을 수 있는 함수는 최소점을 기준으로 왼쪽은 단조감소 오른쪽은 단조증가 해야합니다.

다시말해 지역 곡소점이나 극대점이 반드시 하나 존재해야 하고 이 점이 전역 최대나 최소점이 되어야 합니다.



최대점을 찾아보자

a < b 인 두 점 a, b 가 있고 함수 f(x)의 최대점이 a와 b사이에 있다고 했을 때 a < a' < b' < b 인 a'과 b'을 잡을 수 있습니다.

이때 f(a') < f(b') 이라면 [a, a'] 구간은 단조증가하고 이 구간에 f(b') 보다 더 큰 값을 가지는 점은 없습니다.
따라서 a에 a'을 대입하여 탐색구간을 좁힐 수 있습니다

반대로 f(a') > f(b') 인 경우 b에 b'을 대입하여 탑색구간을 좁힐수 있습니다.


터너리 서치는 기본적으로 위의 아이디어를 가지고 있으며 [a, b] 구간을 3등분 하여 a'과 b'을 정하고. 따라서 한번의 탐색이 이루어질 때마다 탐색구간은 2/3으로 줄어들게 됩니다.


수도코드

// [left, right] 구간내에서 함수 f(x)가 최대인 x를 구한다.
double ternarySearch(int left, int right, function& f)
{
// 적당히 큰 수만큼 반복 -> 오차범위는 (right-left)*(2/3)^(반복횟수)
for (int i = 0; i < 1000; i++) {
double a = (left*2 + right) / 3;
double b = (left + right*2) / 3;

// 최소인 점을 찾으려면 if 문의 부호를 반대로 하면 된다.
if (f(a) < f(b))
left = a;
else
right = b;
}
return (left+right)/2;
}



응용하는 의미에서 문제를 풀어봅시다.

이번 문제는 TopCoder SRM 426 Division1 에서 500점짜리로 나온 문제라 좀 어려운데요.. 터너리서치를 알고있다면 충분히 풀 수 있습니다.


"Catch The Mice" 라는 게임기가 있다. 이 게임기 안에는 장난감 쥐들이 돌아다니고 있다. 플레이어는 우리(cage)를 이동시켜 어느 순간 버튼을 눌러 cage를 떨어뜨려 cage안에 있는 쥐들을 잡을 수 있다.

쥐들은 2차원 평면상을 이동하고 이 평면은 무한히 크다고 가정해도 좋다. cage는 L*L크기의 정사각형이고 cage의 각 모서리는 축에 평행하다. 게임기의 주인은 플레이어가 cage안에 모든 쥐를 다 잡으면 스포츠카를 준다고 했지만 사실은 절대로 그런일이 발생하기를 원하지 않는다.

쥐들의 초기좌표(xp,yp)와 속도(xv,yv)가 주어졌을 때 절대로 모든쥐를 절대로 한번에 못잡게 하는 최대의 cage의 크기 L을 구하라. L의 경계에 걸린 쥐는 잡지 못한것으로 처리된다.

풀이보기