P1378
油滴扩展
题目描述
在一个长方形框子里,最多有 \(N\) 个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这 \(N\) 个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式 \(V = \pi r^2\),其中 \(r\) 为圆的半径。
输入格式
第一行,一个整数 \(N\)。
第二行,四个整数 \(x, y, x', y'\),表示长方形边框一个顶点及其对角顶点的坐标。
接下来 \(N\) 行,第 \(i\) 行两个整数 \(x_i, y_i\),表示盒子内第 \(i\) 个点的坐标。
输出格式
一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)。
样例 #1
样例输入 #1
2
20 0 10 10
13 3
17 7
样例输出 #1
50
提示
对于 \(100\%\) 的数据,\(1 \le N \le 6\),坐标范围在 \([-1000, 1000]\) 内。
dfs
一遍过还是不错
#include<bits/stdc++.h>
using namespace std;
int n,sx,sy,tx,ty;
const double pi=acos(-1);
struct did {
int x,y;
} a[15];
int vis[15];
double r[15];
double maxx=0.0;
double dis(double x,double y,double xx,double yy) {
return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
}
void dfs(int num,double ans) {
if(num==n+1) {
if(ans>maxx+1e-6)maxx=ans;
return ;
}
for(int i=1; i<=n; i++) {
if(vis[i])continue;
double R;
int x=a[i].x,y=a[i].y;
R=min(min(abs(x-sx),abs(x-tx)),min(abs(y-sy),abs(y-ty)));
for(int j=1; j<=n; j++) {
if(j==i)continue;
if(r[j]<0)continue;
R=min(R,dis(x,y,a[j].x,a[j].y)-r[j]);
}
vis[i]=1;
if(R<0.0)R=0.0;
r[i]=R;
dfs(num+1,ans+pi*R*R);
vis[i]=0;
r[i]=-1;
}
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<=n; i++)r[i]=-1;
cin>>sx>>sy>>tx>>ty;
double S=(double)(abs(sx-tx))*(double)(abs(sy-ty));
for(int i=1; i<=n; i++)cin>>a[i].x>>a[i].y;
dfs(1,0.0);
printf("%.0lf\n",S-maxx);
return 0;
}