题目大意:
1 坐标轴内,定义一个方框(知道对角端点);
2 n个点在框内做圆,要求彼此不相交。
3 求最大的覆盖面积。
解题思路:
其实一个全排列的思维就搞定了,只是坐标中的求距离比较繁琐;
1 预处理边界点,我是强行把对角点定义在(左下)和(右上);
2 深搜:依次枚举每个点 i ,求他能扩散的最大面积;
3 和全排列思路一样,根据不同的顺序,选全部点后更新答案。
4 输出框内剩余面积。
上代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double pi=3.141592653,inf=999999999.0;
int n;
double sx,sy,ex,ey,ans=0;
struct nod{int v;double x,y,d;}a[10];
double ss(int x,int y)//求 x点和 y点 的距离
{
double su;
su=sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y));
return su;
}
void dfs(int x,double f)//当前搞定了x个,已经占用面积 f
{
if(x==n) { ans=max(ans,f); return ; } //更新最优解
for(int i=1;i<=n;i++)
if(a[i].v==0)
{
double mi=inf;
//1 处理边界问题
mi=min(mi,min(ex-a[i].x,a[i].x-sx));
mi=min(mi,min(ey-a[i].y,a[i].y-sy));
//2 处理其他点(j)和当前点(i)的问题
for(int j=1;j<=n;j++)
if(a[j].v==1)
{
double dx=ss(i,j);//求出i-j的距离
mi=min(mi,dx-a[j].d);//去掉j点的延伸半径
}
if(mi<0) mi=0.0;//i点被其他迪点覆盖了
a[i].v=1; a[i].d=mi;
dfs(x+1,f+mi*mi);
a[i].v=0; a[i].d=0;
}
}
int main()
{
scanf("%d",&n);
//处理结果保证:左下角是(sx,sy),右上角是(ex,ey);
scanf("%lf%lf%lf%lf",&sx,&sy,&ex,&ey);
if(sx>ex) swap(sx,ex);
if(sy>ey) swap(sy,ey);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&a[i].x,&a[i].y);
a[i].v=a[i].d=0;
}
dfs(0,0);//当前询问了x个,已经占用面积 f
ans=(ex-sx)*(ey-sy)-ans*pi+0.5;//求剩余面积,四舍五入
printf("%d",(int)ans);
return 0;
}