Problem:
Problem B: Carrot Tour

うさぎがある国を旅行している. この国には1 からn の番号がついたn 個の都市があり, うさぎは今都市1にいる. 都市i は座標平面上の1 点(xi, yi) とみなす.

うさぎは以下の条件をみたすように旅をする.

移動経路は折れ線であり, その各部分は異なる2 都市を結ぶ線分でなければならない.

移動経路の全長はr 以下でなければならない. 経路のうち重なった部分も, 通った回数分数える.

移動する方向が変わるとき, 曲がる角度はθ 以下でなければならない. 最初の移動方向に制限はない.

うさぎがある都市から別の都市へ移動をすると, 移動先の都市でニンジンを1 本もらえる. 同じ都市を複数回訪れることは可能であり, 訪れるたびにニンジンをもらえる. うさぎがこの旅で手に入れることのできるニンジンの本数の最大値を求めよ.

Input

入力の一行目には一つの整数n が, 二行目には二つの実数r, θ がスペースで区切られて与えられる.

1 ≤ n ≤ 20

0 < r < 104

0° < θ < 180°

続くn 行には, 整数xi, yi がスペースで区切られて与えられる

-10 000 ≤ xi, yi ≤ 10 000

r, θ を±10−3 以内で変化させても答えは変わらない.

どの2 つの都市の位置も異なる.

Output

うさぎがこの旅で手に入れることのできるニンジンの本数の最大値を一行に出力せよ.

Sample Input 1

5
100.1 90.1
0 0
0 10
5 5
10 0
10 10

Sample Output 1

10

Solution in JAVA (judge verdict: Time Limit Exceeded)

import java.awt.geom.Point2D;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

public class Main {
  final static int INF = 1 << 28;
  final static long LNF = 1L << 60;
  final static long MOD = 1_000_000_007;
  final static double EPS = 1e-9;
  final static double GOLDEN_RATIO = (1.0 + Math.sqrt(5)) / 2.0;
  Scanner sc = new Scanner(System.in);

  public static void main(String[] args) {
    new Main().run();
  }

  static class Point {
    int x, y;

    Point(int a, int b) {
      x = a;
      y = b;
    }

    static Point p(int x, int y) {
      return new Point(x, y);
    }
  }

  double kaku(Point p1, Point p2, Point p3) {
    int dx1 = p2.x - p1.x;
    int dy1 = p2.y - p1.y;
    int dx2 = p3.x - p2.x;
    int dy2 = p3.y - p2.y;

    int naiseki = dx1 * dx2 + dy1 * dy2;
    double z1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
    double z2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);

    return Math.acos(naiseki / (z1 * z2)) * 180 / Math.PI;
  }

  double dist(Point p1, Point p2) {
    double dx = p1.x - p2.x;
    double dy = p1.y - p2.y;
    return Math.sqrt(dx * dx + dy * dy);
  }

  class Node {
    int now;
    int prev;
    int cnt;
    double r;
  }

  void run() {
    int n = ni();
    double r = sc.nextDouble();
    double theta = sc.nextDouble();
    Point[] p = new Point[n];
    for (int i = 0; i < n; ++i) {
      int x = ni();
      int y = ni();
      p[i] = new Point(x, y);
    }
    Node atom = new Node();
    atom.cnt = 0;
    atom.r = 0;
    atom.now = 0;
    atom.prev = -1;
    PriorityQueue<Node> queue = new PriorityQueue<>(Comparator.comparingDouble(a -> a.r));
    queue.add(atom);
    double[][][] dp = new double[n][n + 1][10000 + 1];
    for (double[][] t : dp) for (double[] a : t) Arrays.fill(a, Double.MAX_VALUE);
    while (queue.size() > 0) {
      Node node = queue.poll();
      if (dp[node.now][node.prev + 1][node.cnt] <= node.r) {
        continue;
      }
      dp[node.now][node.prev + 1][node.cnt] = node.r;
      for (int i = 0; i < n; ++i) {
        if (node.now == i) {
          continue;
        }
        if (node.prev == -1 || kaku(p[node.prev], p[node.now], p[i]) <= theta + 1e-3) {
          if (dp[i][node.now + 1][node.cnt + 1] <= node.r) {
            continue;
          }
          Node next = new Node();
          next.now = i;
          next.cnt = node.cnt + 1;
          next.r = node.r + dist(p[node.now], p[i]);
          if (next.r > r + 1e-3) {
            continue;
          }
          next.prev = node.now;
          queue.add(next);
        }
      }
    }
    int max = 0;
    for (int i = 0; i <= 10000; ++i) {
      for (double[][] t : dp) {
        for (double[] a : t) {
          if (a[i] <= r + 1e-3) {
            max = Math.max(max, i);
          }
        }
      }
    }
    System.out.println(max);
  }

  int ni() {
    return Integer.parseInt(sc.next());
  }

  void debug(Object... os) {
    System.err.println(Arrays.deepToString(os));
  }
}