题目描述
在一个长方形框子里,最多有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
【分析】
我堕落了…每天以裸题为生
挺裸的暴搜题…注意π的精度误差,最好赋值为 acos(-1)
枚举油滴放每一个点,然后扫半径最小值就好了…
【代码】
//洛谷 P1378 油滴扩展
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define db double
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const db pi=acos(-1);
db r[10],ans; //r:已扩展半径
int n,xs,ys,xt,yt;
bool vis[10];
int x[10],y[10],mx[10];
inline double calc(int x1,int y1,int x2,int y2)
{
return sqrt((db)(x1-x2)*(db)(x1-x2)+(db)(y1-y2)*(db)(y1-y2));
}
inline void renew()
{
db sum=0;
for(int i=1;i<=n;i++)
sum+=pi*r[i]*r[i];
ans=max(ans,sum);
}
inline void dfs(int dep)
{
int i,j;
if(dep>n) renew();
fo(i,1,n) //选取滴点
if(!vis[i])
{
r[i]=mx[i];
vis[i]=1;
fo(j,1,n)
if(vis[j] && i!=j)
{
db dis=calc(x[j],y[j],x[i],y[i]);
dis=dis-r[j];
r[i]=min(r[i],dis);
if(r[i]<0) r[i]=0;
}
dfs(dep+1);
vis[i]=0;
}
}
int main()
{
int i,j,k;
scanf("%d%d%d%d%d",&n,&xs,&ys,&xt,&yt);
memset(mx,0x3f,sizeof mx);
fo(i,1,n)
{
scanf("%d%d",&x[i],&y[i]);
mx[i]=min(min(abs(xs-x[i]),abs(xt-x[i])),min(abs(ys-y[i]),abs(yt-y[i])));
}
dfs(1);
db tmp=(db)(xs-xt)*(db)(ys-yt);
if(tmp<0) tmp=-tmp;
ans=tmp-ans;
int anss=floor(ans);
if(db(ans-anss)>=0.5) anss++;
printf("%d\n",anss);
return 0;
}