洛谷 1378 油滴扩展
洛谷 1378 油滴扩展
这道题目的方法并不难想,但能做到一遍AC的也一定是真dalao.
首先,需要注意一下此题的要求,油滴是圆形的,各个油滴只能相离或相切。其次,油滴不能覆盖在已有的油滴上,需要进行特判。
#include<bits/stdc++.h> using namespace std; const double pi=3.141592; int n,x,y,x1,yx; int a[7][3]; bool v[7]; double res,outt=-1; double r[7]; double dis(int xx,int yy,int xx1,int yy1) { return sqrt(pow((xx-xx1),2)+pow((yy-yy1),2)); }
dis函数用来计算两点之间的欧几里得距离(勾股定理)。
double minn(int k) { for(int i=1;i<=n;i++) if(i!=k&&v[i]==1) if(r[i]>dis(a[i][1],a[i][2],a[k][1],a[k][2])) return 0; //判断该点坐标是否已被油滴覆盖,是则将该点半径设为零。 double dist; double ans=min(min(abs(a[k][1]-x),abs(a[k][1]-x1)),min(abs(a[k][2]-y),abs(a[k][2]-yx))); //先取该点到边界的最小距离。 for(int i=1;i<=n;i++) if(i!=k&&v[i]==1) { dist=dis(a[i][1],a[i][2],a[k][1],a[k][2])-r[i]; ans=min(ans,dist); } //枚举每个已存在的油滴,更新最小值。 return ans; }
minn函数用来判断圆的最大半径。
void dfs(int k,double res) { double mm; if(k==n) { outt=max(outt,res); return; } for(int i=1;i<=n;i++) if(v[i]==0) { r[i]=minn(i); v[i]=1; dfs(k+1,res+pi*r[i]*r[i]); v[i]=0; r[i]=0; } }
dfs代码,搜索所有可能的顺序。
int main() { scanf("%d",&n); scanf("%d%d%d%d",&x,&y,&x1,&yx); int s=abs(x-x1)*abs(y-yx); //计算总面积 for(int i=1;i<=n;i++) scanf("%d%d",&a[i][1],&a[i][2]); dfs(0,0); cout<<int(s-outt+0.5); //四舍五入 return 0; }
这里需要注意的是输出结果时不能使用如下写法
cout<<floor(s-outt+0.5);
看似这与 int(s-outt+0.5); 并没有区别,但由于精度的问题,这种写法会WA两个点。
例如:正确答案12345678,而用floor函数会得到1.234567e+006
于是乎,我发现:floor 函数的返回值竟然是是 double 型的!
而double类型的小数点6位之后就无法保证精度了。(我的机子上是6位)。
希望对大家有帮助。