题目描述
在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式V=pi*r*r,其中r为圆的半径。
输入输出格式
输入格式:
第1行一个整数N。
第2行为长方形边框一个顶点及其对角顶点的坐标,x,y,x’,y’。
接下去N行,每行两个整数xi,yi,表示盒子的N个点的坐标。
以上所有的数据都在[-1000,1000]内。
输出格式:
一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)
————————————————————————————————————————————————————————
思路:
用枚举全排列来遍历所有滴入油滴的先后顺序
并判断总空间最大的情况
四舍五入后输出答案
代码解释:
#include<iostream>
#include<cmath>
using namespace std;
double x[10],y[10],xa,xb,ya,yb,ans,r[11];
int n;
bool v[10];
double getr(int i)//第i个油滴完全扩散的半径
{
double s1=min(abs(x[i]-xa),abs(x[i]-xb));
double s2=min(abs(y[i]-ya),abs(y[i]-yb));
double o=min(s1,s2);
//为什么是最小的?
//因为油滴只要碰到任何一条边都会全部停止扩散
for(int l=1;l<=n;l++)
{
if(v[l]&&l!=i)
{
double ddd=sqrt((y[l]-y[i])*(y[l]-y[i])+(x[l]-x[i])*(x[l]-x[i]));
o=min(o,max(0.0,ddd-r[l]));
}
}//油滴碰到其他油滴的情况
return o;
}
void dfs(int t,double sum)//t代表该放第t个油滴,sum代表现在的覆盖面积
{
if(t>n)
{
ans=max(sum,ans);
return ;
}
else
{
for(int i=1;i<=n;i++)
if(v[i]==0)
{
v[i]=1;
r[i]=getr(i);
dfs(t+1,sum+3.1415926*r[i]*r[i]);
v[i]=0;//回溯
}
}
}
int main()
{
cin>>n;
cin>>xa>>ya>>xb>>yb;
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i];
double s=abs(xa-xb)*abs(ya-yb);//长方形的面积
dfs(1,0);
cout<<(int)(s-ans+0.5);//手动四舍五入,那个(int)代表输出向下取整的整型变量(嗷嗷嗷,第一次说的这么专业)
return 0;
}