洛谷 P1378 油滴扩展

题目链接:油滴扩展



思路

       枚举油滴滴下的顺序,然后依次判断每个油滴扩展的半径。然后每次计算出当前油滴能扩散的最大半径,通过使用当前油滴与边长的距离。


代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10;
const double PI = 3.1415926535;
bool s[maxn];
double x[maxn], y[maxn], r[maxn], xa, ya, xb, yb, ansmax;
int n;
// 计算当前油滴的扩散半径
double cal(int i) {
  // 计算当前油滴与长方形边框边界的最小距离
  double s1 = min(abs(x[i] - xa), abs(x[i] - xb));
  double s2 = min(abs(y[i] - ya), abs(y[i] - yb));
  double ans = min(s1, s2);
  // 计算当前油滴与其他油滴扩散的圈的半径最小值
  for (int j = 1; j <= n; j++)
    if (i != j && s[j]) {
      double d =
          sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
      ans = min(ans, max(d - r[j], 0.0)); // 如果距离都小于0了,那我还要你有何用
    }
  return ans;
}

// 深搜枚举每个节点的滴落顺序
void dfs(int k, double sum) {
  // 当滴落的油滴数大于n时,取油滴覆盖位置的最大值
  if (k > n) {
    ansmax = max(ansmax, sum);
    return;
  }
  for (int i = 1; i <= n; i++) {
    // 当前油滴是否被枚举,没有则枚举并计算当前油滴扩散的半径
    if (!s[i]) {
      r[i] = cal(i);
      s[i] = 1;
      dfs(k + 1, sum + r[i] * r[i] * PI);
      s[i] = 0;
    }
  }
}

int main() {
  double ss;
  scanf("%d", &n);
  scanf("%lf%lf%lf%lf", &xa, &ya, &xb, &yb);
  ss = abs(xa - xb) * abs(ya - yb);
  for (int i = 1; i <= n; i++)
    scanf("%lf%lf", &x[i], &y[i]);
  dfs(1, 0);
  printf("%d", int(ss - ansmax + 0.5)); // 四舍五入
  return 0;
}
posted @ 2024-06-20 23:15  薛定谔的AC  阅读(17)  评论(0编辑  收藏  举报