P1378 油滴扩展
题目描述
在一个长方形框子里,最多有 $N$ 个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这 $N$ 个点上放置油滴,才能使放置完毕后所有油滴占据的总面积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式 $S = \pi r^2$,其中 $r$ 为圆的半径。
输入格式
第一行,一个整数 $N$。
第二行,四个整数 $x, y, x', y'$,表示长方形边框一个顶点及其对角顶点的坐标。
接下来 $N$ 行,第 $i$ 行两个整数 $x_i, y_i$,表示盒子内第 $i$ 个点的坐标。
输出格式
一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)。
输入输出样例 #1
输入 #1
输出 #1
说明/提示
对于 $100%$ 的数据,$1 \le N \le 6$,坐标范围在 $[-1000, 1000]$ 内。
题解
本题意思是:在一个地方依次放n个点,他们扩散成圆,彼此不重合也不超过边界
我们可以用DFS来枚举每个点的放置顺序,计算每个点的扩散半径,最后求出剩余空间的最小值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <bits/stdc++.h> using namespace std; const double PI = acos(-1); typedef long long ll;
int main(){ ios::sync_with_stdio(false); cin.tie(0); ll n; ll x, y, x1, y1; cin >> n >> x >> y >> x1 >> y1; double L = min(x, x1), R = max(x, x1), U = max(y, y1), D = min(y, y1); double ans = 0; vector<pair<ll, ll>> loc(n); for(auto &[xx, yy] : loc) cin >> xx >> yy; vector<double> r(n); vector<bool> vis(n); function<double(ll)> get_r = [&](ll i) { double ansr = min({loc[i].first - L, R - loc[i].first, loc[i].second - D, U - loc[i].second}); for (ll j = 0; j < n; j++) { if (vis[j]) { ansr = min(ansr, (double)sqrt(pow(loc[i].first - loc[j].first, 2) + pow(loc[i].second - loc[j].second, 2)) - r[j]); } } ansr = max(ansr, 0.0); return ansr; }; function<void(ll, double)> dfs = [&](ll k, double sum){ if (k == n){ ans = max(ans, sum); return; } for(ll i = 0; i < n; i++){ if (!vis[i]){ r[i] = get_r(i); vis[i] = true; dfs(k + 1, sum + r[i] * r[i] * PI); vis[i] = false; } } }; dfs(0, 0); cout << (ll)round((R - L) * (U - D) - ans) << endl; return 0; }
|