春测T3贪心求证明或证伪
  • 板块学术版
  • 楼主GoldenFishX
  • 当前回复2
  • 已保存回复2
  • 发布时间2023/3/5 14:42
  • 上次更新2023/10/23 22:58:50
查看原帖
春测T3贪心求证明或证伪
156353
GoldenFishX楼主2023/3/5 14:42

rt,从k号点开始,每次选择连到左边的点还是右边的点,用dp解决,以这张图为例 从5开始走,会走出5->4->3->6->...或5->6->4->3->2->...之类的路径,但不会出现5->2->6->...这样跨点走的路径

代码如下

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e3 + 5;

int s[MAXN];
int cnt = 0;

double dp[MAXN][MAXN][2];

struct Node {
  double x, y;
  Node operator-(const Node& xx) const { return {x - xx.x, y - xx.y}; }
} a[MAXN];

double x(Node a, Node b) {
  return a.x * b.y - a.y * b.x;
}

double l(Node &a, Node &b) {
  return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

double dis(Node &a, Node &b) {
  return sqrt(l(a, b));
}

bool cmp(Node a1, Node a2) {
  if (x(a1 - a[0], a2 - a[0]) != 0) {
    return x(a1 - a[0], a2 - a[0]) > 0;
  }
  return l(a1, a[0]) < l(a2, a[0]);
}

int anss[MAXN];

int main() {
  cin.tie(0), cout.tie(0);
  ios_base::sync_with_stdio(0);
  int n, k = 0;
  double ans = 1e12;
  cin >> n;
  for (int i = 0; i < n; i++) {
    cin >> a[i].x >> a[i].y;
  }
  double minx = 1145141919, miny = 1145141919, maxy;
  int mini;
  // for (int i = 0; i < n; i++) { //(这个傻逼没看清题目以为点是不按照凸边形顺序给的然后脑残写了个凸包)
  //   if (a[i].x < minx || (a[i].x == minx && a[i].y < miny)) {
  //     minx = a[i].x, miny = a[i].y, mini = i;
  //   }
  // }
  // swap(a[0], a[mini]);
  // sort(a + 1, a + n, cmp);
  // s[cnt++] = 0;
  // for (int i = 1; i <= n; i++) {
  //   while (x(a[s[cnt - 1]] - a[s[cnt - 2]], a[i % n] - a[s[cnt - 1]]) < 0) {
  //     cnt--;
  //   }
  //   s[cnt++] = i % n;
  // }
  for (int i = 0; i <= n; i++) {
    s[i] = i;
  }
  maxy = a[s[0]].y;
  for (int i = 1; i < n; ++i) {
    if (maxy < a[s[i]].y) {
      maxy = a[s[i]].y;
      k = i;
    }
  }

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      dp[i][j][0] = dp[i][j][1] = 1e12;
    }
  }
  dp[0][0][0] = dp[0][0][1] = 0;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j + i + 1 < n; ++j) {
      int uu0 = s[(n * 2 + k - i) % n], uu1 = s[(k + j) % n], vv0 = s[(2 * n + k - i - 1) % n], vv1 = s[(k + j + 1) % n];
      dp[i + 1][j][0] = min(dp[i][j][0] + dis(a[uu0], a[vv0]), dp[i][j][1] + dis(a[uu1], a[vv0]));
      dp[i][j + 1][1] = min(dp[i][j][0] + dis(a[uu0], a[vv1]), dp[i][j][1] + dis(a[uu1], a[vv1]));
    }
  }
  int ii, jj, ff;
  for (int i = 0, j; i < n; ++i) {
    j = n - i - 1;
    if (ans > dp[i][j][0]) {
      ii = i, jj = j, ff = 0;
      ans = dp[i][j][0];
    }
    if (ans > dp[i][j][1]) {
      ii = i, jj = j, ff = 1;
      ans = dp[i][j][1];
    }
  }
  int cntt = 0;
  anss[cntt++] = (k + jj) % n;
  while (ii || jj) {
    if (!ff) {
      int i = ii - 1, j = jj;
      int uu0 = s[(n * 2 + k - i) % n], uu1 = s[(k + j) % n], vv0 = s[(2 * n + k - i - 1) % n], vv1 = s[(k + j + 1) % n];
      if (dp[i + 1][j][0] == dp[i][j][0] + dis(a[uu0], a[vv0])) {
        ii = i, jj = j, ff = 0;
        anss[cntt++] = (2 * n + k - ii) % n;
      } else if (dp[i + 1][j][0] == dp[i][j][1] + dis(a[uu1], a[vv0])) {
        ii = i, jj = j, ff = 1;
        anss[cntt++] = (k + jj) % n;
      }
    } else {
      int i = ii, j = jj - 1;
      int uu0 = s[(n * 2 + k - i) % n], uu1 = s[(k + j) % n], vv0 = s[(2 * n + k - i - 1) % n], vv1 = s[(k + j + 1) % n];
      if (dp[i][j + 1][1] == dp[i][j][0] + dis(a[uu0], a[vv1])) {
        ii = i, jj = j, ff = 0;
        anss[cntt++] = (2 * n + k - ii) % n;
      } else {
        ii = i, jj = j, ff = 1;
        anss[cntt++] = (k + jj) % n;
      }
    }
  }
  // printf("%.4lf", ans);
  for (int i = cntt - 1; i > -1; --i) {
    cout << anss[i] + 1 << ' ';
  }
  return 0;
}
2023/3/5 14:42
加载中...