競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 151F問題

\(\def \set #1#2{\{ #1 \ \vert \ #2 \}}\)

ABC151F

解法

最小包含円を求めるアルゴリズムが知られている. 下に凸な関数に対して三分探索を二回用いる.
\(P := {P_{i}}_{i \in N}\) を平面の点の集合とする. \(f_{P}(x,y) := \) 点 \(\ (x,y)\ \) から\(P\) の距離への最大値とする. すなわち,

\(f_{P}(x,y) := max_{i \in N} \ dist*1;
  };

  // f: 下に凸
  // rem: 三分探索なので,分母は 3.
  // rem: 三分探索なので,区間の幅が 2/3倍になる.
  // 0.66 ^80 < 3.661e-15
  auto tri = [](auto f) -> double {
    double l = 0, r = 2005;
    rep(i,80){
      double cl = (l*2 + r) / 3.;
      double cr = (l + r*2) / 3.;

      if(f(cl) < f(cr)) r = cr; // not f(cl) < cr
      else l = cl;
    }
    return f(l);
  };

  auto f = [=](double x, double y) -> double {
    double ret = -1;
    rep(i,n){
      double d = dis(x,y, p[i].first, p[i].second);
      chmax(ret, d);
    }
    return ret;
  };

  auto g = [=](double x) -> double {
    return tri( [&](double y){return f(x,y);} );
  };

  printf("%.10lf\n", tri(g));
 
  return 0;
}

*1:x,y), P_{i})\)

とする. \(g_{P}(x)\) を,

\(g_{P}(x) := min_{y \in \mathbb{R}} \ f_{P}(x,y)\)

とおく. 最小包含円の半径は, \[\begin{eqnarray} && min_{x \in \mathbb{R}} \ min_{y \in \mathbb{R}} \ f_{P}(x,y) \\ &=& min_{x \in \mathbb{R}} \ \ g_{P}(x) \end{eqnarray}\] となる. \(f\) は,\(x\) を定数,\(y\) を変数とみなしたときに下に凸であり, \(g\) は 変数\(x\) について下に凸な関数となる ので,それぞれ三分探索で min が求まる.

使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"

int main() {
  ll n;
  cin >> n;

  vector<pll> p(n);
  rep(i,n){
    cin >> p[i].first >> p[i].second;
  }

  auto dis = [](double x, double y, double z, double w) -> double {
    return sqrt(square(x-z) + square(y-w