← Все вопросы

Оптимальная триангуляция выпуклого многоугольника через interval DP — как считать минимальный периметр?

Задан 5 месяцев назад869 просмотров2 ответа
8

Дан выпуклый многоугольник вершинами pt[0..n-1] по обходу. Нужно разбить его непересекающимися диагоналями на треугольники так, чтобы суммарная длина всех проведённых диагоналей (или суммарный периметр треугольников) была минимальна. Это похоже на цепочку матриц, но не пойму, как тут отрезок.

2 ответа

12
✓ Принятый ответ — помог автору

Да, это interval DP с той же структурой, что и матрицы. Трюк — отрезок [i..j] = подмногоугольник на вершинах от i до j плюс ребро (i, j). Мы перебираем третью вершину k треугольника, опирающегося на ребро (i, j):

dp[i][j] = минимальная стоимость триангуляции подмногоугольника i, i+1, ..., j (где (i,j) — фиксированное ребро/диагональ-основание).

int n;
double x[1005], y[1005];
auto d = [&](int a, int b) {
  return hypot(x[a] - x[b], y[a] - y[b]);
};
vector<vector<double>> dp(n, vector<double>(n, 0));

for (int len = 2; len < n; ++len)        // расстояние между i и j
  for (int i = 0; i + len < n; ++i) {
    int j = i + len;
    dp[i][j] = 1e18;
    for (int k = i + 1; k < j; ++k) {
      double cost = dp[i][k] + dp[k][j]
                  + d(i, k) + d(k, j) + d(i, j); // периметр треуг.
      dp[i][j] = min(dp[i][j], cost);
    }
  }
// ответ dp[0][n-1]

Если минимизируешь только сумму диагоналей (а не периметр), не добавляй стороны самого многоугольника — добавляй лишь те рёбра треугольника, которые являются диагоналями. Сложность $O(n^3)$ времени, $O(n^2)$ памяти.

3

Важно: формула работает именно потому, что многоугольник выпуклый — тогда любая хорда (i,j) лежит внутри и не пересекает стороны, а подмногоугольники [i..k] и [k..j] не накладываются. Для невыпуклого это неверно (диагонали могут выходить наружу), и задача становится сложнее. На олимпиадах в условии почти всегда явно пишут «выпуклый» — это сигнал именно к такому ДП.

Ваш ответ

Войдите, чтобы ответить на вопрос.