2020-1ํ•™๊ธฐ, ๋Œ€ํ•™์—์„œ โ€˜์•Œ๊ณ ๋ฆฌ์ฆ˜โ€™ ์ˆ˜์—…์„ ๋“ฃ๊ณ  ๊ณต๋ถ€ํ•œ ๋ฐ”๋ฅผ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ์ง€์ ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜์ž…๋‹ˆ๋‹ค :)

6 minute read

2020-1ํ•™๊ธฐ, ๋Œ€ํ•™์—์„œ โ€˜์•Œ๊ณ ๋ฆฌ์ฆ˜โ€™ ์ˆ˜์—…์„ ๋“ฃ๊ณ  ๊ณต๋ถ€ํ•œ ๋ฐ”๋ฅผ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ์ง€์ ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜์ž…๋‹ˆ๋‹ค :)

๋ฐฑ์ค€ 2261๋ฒˆ: ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋‘ ์  ๋ฌธ์ œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘์„ฑ๋œ ํฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.


<closest pair of points> ๋ฌธ์ œ๋Š” $n$๊ฐœ์˜ ์ ์ด ์žˆ๋Š” ํ‰๋ฉด์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์œ ํด๋ฆฌ๋“œ ๊ฑฐ๋ฆฌ๋ฅผ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค. ์ด ๋ฌธ์ œ๋Š” ๊ณตํ•ญ ๊ด€์ œํƒ‘์—์„œ ๋‘ ๋น„ํ–‰๊ธฐ๊ฐ€ ์ถฉ๋Œํ• ์ง€๋ฅผ ํ™•์ธํ•˜๊ณ  ์ž๋™์œผ๋กœ ์•Œ๋ ค์ฃผ๋Š” ์‹œ์Šคํ…œ ๋“ฑ์—์„œ ๋น ๋ฅด๊ฒŒ ๊ฒฝ๋ณด๋ฅผ ์šธ๋ฆฌ๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

Brute Force ํ•˜๊ฒŒ ์ ‘๊ทผํ•œ๋‹ค๋ฉด ๋ชจ๋“  ๋‘ ์ ์˜ ์Œ์— ๋Œ€ํ•ด ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•ด ์ตœ์†Œ ๊ฑฐ๋ฆฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ๋ฐฉ๋ฒ•์€ $O(n^2)$์˜ ๋น„์šฉ์„ ํ•„์š”๋กœ ํ•œ๋‹ค. ์šฐ๋ฆฌ๋Š” Divide and Conquer๋กœ ์ ‘๊ทผํ•ด $O(n \log n)$์˜ ๋น„์šฉ์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ฒƒ์ด๋‹ค! ๐Ÿ™Œ

1. Sort points in $P$ by $x$-coordinates: $P_x$. And calculate $x$-median $x_{\text{mid}}$

2. Divide the point set $P$ into two equal-sized subsets $P^{L}$ and $P^{R}$ along $x_{\text{mid}}$. And then solve the problem(= find the closest pair in subsets) for two subsets respectively.

3. Choose the minimum of the tow smallest distances, returned from each subproblem: denote it as $\delta$.

4. ์•„๋ž˜์—์„œ ๊ณ„์†โ€ฆ

delta $\delta$๋ฅผ ๊ตฌํ–ˆ๋‹ค๋ฉด, ์ด์ œ๋Š” $P^L$, $P^R$์— ๊ฑธ์ณ์„œ ์กด์žฌํ•˜๋Š” ๊ฑฐ๋ฆฌ๋“ค์„ ์‚ดํŽด๋ด์•ผ ํ•œ๋‹ค. ์ด๋Š” $x_{\text{mid}}$์—์„œ ์ขŒ์šฐ๋กœ $\delta$ ๋งŒํผ์˜ ๊ฑฐ๋ฆฌ์— ์žˆ๋Š” ์ ๋“ค์„ ์‚ดํŽด๋ณด๋ฉด ๋œ๋‹ค. $2\delta$ ๊ธธ์ด ๋งŒํผ์˜ ํšŒ์ƒ‰ ๋ ์— ์†ํ•˜๋Š” ์ ๋“ค์€ $O(n)$์˜ ๋น„์šฉ์œผ๋กœ ์‰ฝ๊ฒŒ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํšŒ์ƒ‰ ๋ ์— ์†ํ•˜๋Š” ์ ๋“ค์„ ๋ชจ๋‘ ๊ตฌํ–ˆ๋‹ค๋ฉด ์ด๋ฒˆ์—๋Š” $y$-coordinate๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ $P_y$๋ฅผ ์œ ๋„ํ•œ๋‹ค.

ํšŒ์ƒ‰ ๋  ๋‚ด๋ถ€๋ฅผ $\delta/2$ ๊ธธ์ด ๋งŒํผ์˜ cell๋กœ ๋ถ„ํ• ํ•˜์ž. ๊ทธ๋ฆฌ๊ณ  $s_i$๋ฅผ $P_y$์—์„œ $i$๋ฒˆ์งธ๋กœ ์ž‘์€ $y$ ์ขŒํ‘œ๋ฅผ ๊ฐ–๋Š” ์ ์ด๋ผ๊ณ  ํ•˜์ž. ๊ทธ๋Ÿฌ๋ฉด ์•„๋ž˜์˜ ํšŒ์ƒ‰ ๋ ์˜ cell์— ๋Œ€ํ•ด ์•„๋ž˜ ๋ฌธ์žฅ์ด ์„ฑ๋ฆฝํ•œ๋‹ค!

  • No two points lie in same $\delta/2 \times \delta/2$ box.
    • ๋งŒ์•ฝ ๊ทธ๋Ÿฐ ์ ์ด ์กด์žฌํ•œ๋‹ค๋ฉด subproblem์„ ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์—์„œ $\le \delta/2$๊ฐ€ ์ตœ์†Œ ๊ฑฐ๋ฆฌ๋กœ ๋ฝ‘ํ˜”์–ด์•ผ ํ•œ๋‹ค.
  • Two points at least 2 rows apart have distance $\ge \delta$.
    • ๋‹น์—ฐ!
  • If $\left| i - j \right| \ge 12$, then the distance between $s_i$ and $s_j$ is at least $\delta$.
    • ์ด๊ฒƒ์€ 1, 2๋ฒˆ์งธ ๋ฌธ์žฅ์œผ๋กœ ์œ ๋„๋˜๋Š” ๊ฑด๋ฐ $i$๋ฅผ ๊ธฐ์ค€์œผ๋กœ 12๊ฐœ์˜ cell์„ ์ง€๋‚˜๋ฉด ๊ธธ์ด๊ฐ€ ๋ฌด์กฐ๊ฑด $\delta$๋ณด๋‹ค ์ปค์ง„๋‹ค๋Š” ๋ง์ด๋‹ค.

์œ„์˜ ๋ฌธ์žฅ๋“ค, ํŠนํžˆ 3๋ฒˆ ๋ฌธ์žฅ์œผ๋กœ ์ธํ•ด ์šฐ๋ฆฌ๋Š” $P_y$์— ์†ํ•œ ๊ฐ ์  $s_i$์— ๋Œ€ํ•ด $s_{i+1}$๋ถ€ํ„ฐ $s_{i+11}$๊นŒ์ง€ ๋„๋Š” 2์ค‘ for๋ฌธ์„ ๋Œ๋ฉด ํšŒ์ƒ‰ ๋ ์—์„œ ์ „์ฒด ์  ์Œ์„ ํ™•์ธํ•  ํ•„์š” ์—†์ด $O(12 n)$์˜ ๋น„์šฉ์œผ๋กœ smallest distance๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค!


์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๋ถ„์„ํ•ด๋ณด๋ฉด

  • ์ œ์ผ ์ฒ˜์Œ์— ๋“ค์ธ point sort: $O(n \log n)$
  • ๋ถ„ํ•  ์ •๋ณต: $T(n) \le 2 T(n/2) + O(n) \implies T(n) = O(n \log n)$

๋กœ $O(n \log n)$์˜ ๋น„์šฉ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค!!


Code Implementation

์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋ณต์žกํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๋„ ์กฐ๊ธˆ ๋ณต์žกํ•˜๋‹ค.

#define Point pair<int, int>
#define point_vec vector<Point>

point_vec points;

long long dist(Point p1, Point p2){
    return (p1.first - p2.first)*(p1.first - p2.first) + (p1.second - p2.second)*(p1.second - p2.second);
}

์ฝ”๋“œ ์ž‘์„ฑ์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด Point์™€ point_vec ํƒ€์ž…์„ ์„ ์–ธํ•˜๊ณ , ํฌ์ธํŠธ ๊ฑฐ๋ฆฌ ํ•จ์ˆ˜ dist๋ฅผ ์ •์˜ํ•œ๋‹ค. ์ œ๊ณฑ๊ทผ๊นŒ์ง€ ๊ตฌํ•  ํ•„์š”๋Š” ์—†๋‹ค.

// ์ฝ˜์†” ์ž…๋ ฅ
...
sort(points.begin(), points.end());

printf("%lld", ClosestPair(points));

๊ฐ’์„ ์ž…๋ ฅ ๋ฐ›์€ ํ›„์—๋Š” $x$๊ฐ’์— ๋”ฐ๋ผ point ๋ฐฐ์—ด์„ ์ •๋ ฌํ•œ๋‹ค.

long long ClosestPair(point_vec Px){
    // base case
    if(Px.size() == 2)
        return dist(Px[0], Px[1]);
    if(Px.size() == 3)
        return min({dist(Px[0], Px[1]), dist(Px[0], Px[2]), dist(Px[1], Px[2])});

    int N = Px.size();

    /* divide */
    int mid = N / 2;

    /* Px_L, Px_R */
    point_vec Px_L = point_vec(Px.begin(), Px.begin() + mid);
    point_vec Px_R = point_vec(Px.begin() + mid, Px.end());

    long long d1 = ClosestPair(Px_L);
    long long d2 = ClosestPair(Px_R);
    long long d = min(d1, d2);

    ....
}

๋ช‡๊ฐ€์ง€ ๋ฒ ์ด์Šค ์ผ€์ด์Šค๋“ค์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ํฌ์ธํŠธ ์ง‘ํ•ฉ $P_x$๋ฅผ ๋ถ„ํ• ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค. ๊ฐ๊ฐ์—์„œ ์–ป์€ d1, d2์—์„œ์˜ ์ตœ์†Ÿ๊ฐ’์„ d์— ์ €์žฅํ•œ๋‹ค.

  /* merge */
  Point point_mid = Px[mid];
  point_vec Sy;
  long long sqrt_d = sqrt(d);
  for(int i = mid; i >= 0; i--){
      if(abs(point_mid.first - Px[i].first) <= sqrt_d)
          Sy.push_back(Px[i]);
      else
          break;
  }
  for(int i = mid + 1; i < N; i++){
      if(abs(point_mid.first - Px[i].first) <= sqrt_d)
          Sy.push_back(Px[i]);
      else
          break;
  }

๋‹ค์Œ์€ ๊ฐ€์šด๋ฐ์˜ ํšŒ์ƒ‰ ๋ ์— ์†ํ•˜๋Š” ์ ๋“ค $S_y$ ์ฐพ๋Š” ์ž‘์—…์ด๋‹ค. $O(n)$์˜ ๋น„์šฉ์ด ๋“ ๋‹ค.

  bool yComparator(Point p1, Point p2){
      return p1.second < p2.second;
  }
  ...
  /* sort points in increasing y coordinate */
  sort(Sy.begin(), Sy.end(), yComparator);

  int CrossN = Sy.size();
  for(int i = 0; i < CrossN; i++){
      for(int j = i + 1; j < min(CrossN, i + 12); j++){
          d = min(d, dist(Sy[i], Sy[j]));
      }
  }

  return d;

$S_y$์˜ ์ ๋“ค์„ $y$-์ขŒํ‘œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค. ๊ทธ๋ƒฅ ์ •๋ ฌํ•˜๊ฒŒ ๋˜๋ฉด $x$-์ขŒํ‘œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ Comparator๋ฅผ ์ •์˜ํ•ด์„œ ์ธ์ž๋กœ ๋„ฃ์–ด์ค€๋‹ค. ๊ทธ ํ›„์—๋Š” $S_y$์— ์†ํ•˜๋Š” ์ ๋“ค์„ ์ˆœํšŒํ•˜๋ฉฐ ๋’ค์˜ 12๊ฐœ์˜ ์ ๋“ค๊ณผ์˜ ๊ฑฐ๋ฆฌ๋ฅผ ์žฐ๋‹ค. $O(n * 12)$์˜ ๋น„์šฉ์ด ๋“ ๋‹ค.


<closest pair of points>๋ฅผ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ •๊ทœ ์ˆ˜์—…์—์„œ ๋‹ค๋ฃฌ ๋ชจ๋“  ๋ถ„ํ•  ์ •๋ณต์˜ ๋ฌธ์ œ๋“ค์„ ์‚ดํŽด๋ณด์•˜๋‹ค ๐Ÿ‘

Categories:

Updated: