P1378 油滴扩展

题目描述

在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)

注:圆的面积公式V=pi*r*r,其中r为圆的半径。

输入输出格式

输入格式:

第1行一个整数N。

第2行为长方形边框一个顶点及其对角顶点的坐标,x,y,x’,y’。

接下去N行,每行两个整数xi,yi,表示盒子的N个点的坐标。

以上所有的数据都在[-1000,1000]内。

输出格式:

一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)

输入输出样例

输入样例#1: 复制
2
20 0 10 10
13 3
17 7
输出样例#1: 复制
50

没啥好说的,纯dfs+几何
// 去吧!皮卡丘! 把AC带回来!
//      へ     /|
//   /\7    ∠_/
//   / │   / /
//  │ Z _,< /   /`ヽ
//  │     ヽ   /  〉
//  Y     `  /  /
//  イ● 、 ●  ⊂⊃〈  /
//  ()  へ    | \〈
//   >ー 、_  ィ  │ //
//   / へ   / ノ<| \\
//   ヽ_ノ  (_/  │//
//    7       |/
//    >―r ̄ ̄`ー―_
//**************************************
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 2147483647
const ll INF = 0x3f3f3f3f3f3f3f3fll;
#define ri register int
template <class T> inline T min(T a, T b, T c) { return min(min(a, b), c); }
template <class T> inline T max(T a, T b, T c) { return max(max(a, b), c); }
template <class T> inline T min(T a, T b, T c, T d) {
  return min(min(a, b), min(c, d));
}
template <class T> inline T max(T a, T b, T c, T d) {
  return max(max(a, b), max(c, d));
}
#define scanf1(x) scanf("%d", &x)
#define scanf2(x, y) scanf("%d%d", &x, &y)
#define scanf3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define scanf4(x, y, z, X) scanf("%d%d%d%d", &x, &y, &z, &X)
#define pi acos(-1)
#define me(x, y) memset(x, y, sizeof(x));
#define For(i, a, b) for (int i = a; i <= b; i++)
#define FFor(i, a, b) for (int i = a; i >= b; i--)
#define bug printf("***********
");
#define mp make_pair
#define pb push_back
const int maxn = 3e5 + 10;
const int maxx = 1e6 + 10;
// name*******************************
int n;
double a1, a2, b1, b2;
struct point {
  double x, y;
} p[10];
double ans = 0;
bool book[10];
double R[10], r[10];
double tot;
// function******************************
//计算两点距离
double dist(int a, int b) {
  return sqrt((p[a].x - p[b].x) * (p[a].x - p[b].x) +
              (p[a].y - p[b].y) * (p[a].y - p[b].y));
}
//计算边界最短距离
double cal(int i) {
  return min(fabs(p[i].x - a1), fabs(p[i].x - a2), fabs(p[i].y - b1),
             fabs(p[i].y - b2));
}

//核心代码搜素
void dfs(int cnt, double sum) {
  if (cnt == n) {
    ans = max(ans, sum);
    return;
  }
  For(i, 1, n) {
    if (book[i])
      continue;
    r[i] = R[i];
    For(j, 1, n) {
      if (book[j]) {
        if (dist(i, j) <= r[j]) {
          r[i] = 0;
          break;
        } else {
          r[i] = min(r[i], dist(i, j) - r[j]);
        }
      }
    }
    double s = pi * r[i] * r[i];
    book[i] = 1;
    dfs(cnt + 1, sum + s);
    book[i] = 0;
  }
}

//***************************************
int main() {
  // ios::sync_with_stdio(0); cin.tie(0);
  // freopen("test.txt", "r", stdin);
  //  freopen("outout.txt","w",stdout);
  cin >> n;
  cin >> a1 >> b1 >> a2 >> b2;
  tot = fabs(a1 - a2) * fabs(b1 - b2);
  For(i, 1, n) {
    cin >> p[i].x >> p[i].y;
    R[i] = cal(i);
  }
  if (n == 0) {
    cout << tot;
    return 0;
  }
  dfs(0, 0);
  double t = tot - ans;
  double yu = t - (int)t;
  if (yu > 0.5)
    cout << (int)t + 1;
  else
    cout << (int)t;

  return 0;
}
原文地址:https://www.cnblogs.com/planche/p/8556919.html