luogu1378油滴扩散(深搜)

题目连接

#同类的题目还有这些#

题目大意:

    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;
}


猜你喜欢

转载自blog.csdn.net/liusu201601/article/details/79813175
今日推荐