洛谷1378
一道面向过程的搜索题
如果采用模块化的思想这道题会很好写。
先用dfs求出全排列,
然后我们写一个place函数,处理所有的拓展油滴情况即可
这样能够避免头晕以及不必要的调试。
#include<stdio.h>
#include<cmath>
#include<algorithm>
using namespace std;
int control[6];bool book[6];//存储全排列
int n;double res;
double d[6][6];
struct circle
{
int x;int y;double r;
}c[6];
int x3;int y3;int x2;int y2;
double place(int p)//拓展油滴函数
{
double minp=0x3f3f3f3f;double
t=abs(x3-c[p].x);minp=min(minp,t);//printf("minpis%.4f\n",minp);
t=abs(x2-c[p].x);minp=min(minp,t);//printf("minpis%.4f\n",minp);
t=abs(y3-c[p].y);minp=min(minp,t);//printf("minpis%.4f\n",minp);
t=abs(y2-c[p].y);minp=min(minp,t);//printf("minpis%.4f\n",minp);//更新四边距离
for(int i=0;i<n;i++)
{
if(i==p)continue;//不能计算到自己的距离
if(c[i].r>-0.000001&&c[i].r<0.000001)//如果目标点半径为0即跳过
continue;
t=d[p][i]-c[i].r;
if(t<0.00001)return 0;//如果在油滴内部无法拓展
minp=min(minp,t);//printf("minpis%.4f\n",minp);
}
c[p].r=minp;
return minp*minp;//return的是r^2最后再乘π
}
void clear()//清空半径
{
for(int i=0;i<n;i++)
{
c[i].r=0;
}return;
}
void dfs(int x)//求全排列
{
if(x==n)
{
double rep=0;
for(int i=0;i<n;i++)//按排列顺序放置油滴
{
rep+=place(control[i]);
}
if(res<rep)res=rep;
clear();//记得清空半径
return;
}
else//全排列模板
{
for(int i=0;i<n;i++)
{
if(!book[i])
{
book[i]=true;
control[x]=i;
dfs(x+1);
book[i]=false;
}
}
}
return ;
}
int main()
{
scanf("%d",&n);
scanf("%d%d%d%d",&x3,&y3,&x2,&y2);
for(int i=0;i<n;i++)
{
scanf("%d%d",&c[i].x,&c[i].y);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
d[j][i]=d[i][j]=
sqrt((c[i].x-c[j].x)*(c[i].x-c[j].x)+(c[i].y-c[j].y)*(c[i].y-c[j].y));
//printf("d[%d][%d]is%f\n",i,j,d[i][j]);
//计算任意两点距离
}
}
dfs(0);//dfs
res*=3.1415926;//由于res是Σri^2所以要乘π
res=abs(x3-x2)*abs(y3-y2)-res+0.5;//减总面积,四舍五入
int ans=res;
printf("%d",ans);
return 0;
}
posted on 2017-10-15 17:05 SHADOWICENCXIX 阅读(119) 评论(0) 编辑 收藏 举报