原题链接:https://www.luogu.com.cn/problem/P1378
在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式V=pi*r*r,其中r为圆的半径。
第1行一个整数N。
第2行为长方形边框一个顶点及其对角顶点的坐标,x,y,x’,y’。
接下去N行,每行两个整数xi,yi,表示盒子的N个点的坐标。
以上所有的数据都在[-1000,1000]内。
一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)
2 20 0 10 10 13 3 17 7
50
主要思路:
这是一道搜索题,因为n<=6,可以枚举所有的油滴放置顺序,计算油渍面积最大值再用总面积减去,得到答案。
首先与处理出任意两点之间的距离,然后在处理每个点与矩形四个边的最小距离。
然后搜索出所有的滴油顺序,求出面积。
每个油滴的扩展范围可以求出它到矩形边最小距离,与别的油滴之间距离减去那个油滴半径,这些值得最小一个即为此油滴的半径。
有几个要注意的地方:
1.一个油滴在另一个内部时不能扩展,即要把半径设为零不然有可能出现负数的半径。
2.四舍五入的是后c++不要直接int,要先加0.5,pascal应该用round();
3.如果不知道π是多少可以在c++中#include<math.h>然后按住Ctrl点击头文件名,在math.h中可以找到π的值。
下面是代码:
c/c++:
#include<stdio.h> #include<math.h> double a[7][7]; double sj[7][2]; double xx1,yy1,x2,y2,minn,anm=0; double bl[7]; int n; double abss(double kk){ return kk>=0?kk:(-kk);} void ss(int k){ if(k==n){ double s=0; for(int i=1;i<=n;i++)s+=bl[i]*bl[i]; if(s>anm)anm=s; return; } for(int i=1;i<=n;i++)if(bl[i]==-1){ double minm=a[i][0]; for(int j=1;j<=n;j++)if(bl[j]!=-1) if(a[i][j]-bl[j]<minm)minm=a[i][j]-bl[j]; if(minm<0)minm=0; bl[i]=minm; ss(k+1); bl[i]=-1; } return;} int main(){ for(int i=0;i<=6;i++)bl[i]=-1; scanf("%d%lf%lf%lf%lf",&n,&xx1,&yy1,&x2,&y2); for(int i=1;i<=n;i++)scanf("%lf%lf",&sj[i][0],&sj[i][1]); for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) a[i][j]=a[j][i]=sqrt((sj[i][0]-sj[j][0])*(sj[i][0]-sj[j][0])+(sj[i][1]-sj[j][1])*(sj[i][1]-sj[j][1])); for(int i=1;i<=n;i++){ minn=abss(sj[i][0]-xx1); if(abss(sj[i][0]-x2)<minn)minn=abss(sj[i][0]-x2); if(abss(sj[i][1]-yy1)<minn)minn=abss(sj[i][1]-yy1); if(abss(sj[i][1]-y2)<minn)minn=abss(sj[i][1]-y2); a[i][0]=a[0][i]=minn; } ss(0); double h=anm*3.14159265358979323846; double s1=abss(x2-xx1)*abss(y2-yy1); int zj=(int)(s1-h+0.5); printf("%d",zj); return 0;}
pascal:
var a:array[0..7,0..7]of real; sj:array[0..7,0..2]of real; bl:array[0..7]of real; xx1,yy1,x2,y2,minn,anm,h,s1:real; n,zj:longint; function abss(kk:real):real; begin if kk>=0 then exit(kk) else exit(kk*(-1)); end; procedure ss(k:longint); var s,minm:real; i1,j1:longint; begin if k=n then begin s:=0; for i1:=1 to n do s:=s+(bl[i1]*bl[i1]); if s>anm then anm:=s; exit(); end; for i1:=1 to n do begin if bl[i1]=-1then begin minm:=a[i1,0]; for j1:=1 to n do if (bl[j1]<>-1) and ((a[i1,j1]-bl[j1])<minm) then minm:=a[i1,j1]-bl[j1]; if minm<0 then minm:=0; bl[i1]:=minm; ss(k+1); bl[i1]:=-1; end; end; exit(); end; var i,j:longint; begin anm:=0; for i:=1 to 6 do bl[i]:=-1; readln(n); readln(xx1,yy1,x2,y2); for i:=1 to n do read(sj[i,0],sj[i,1]); for i:=1 to n do for j:=1 to n do begin a[j,i]:=sqrt((sj[i,0]-sj[j,0])*(sj[i,0]-sj[j,0])+(sj[i,1]-sj[j,1])*(sj[i,1]-sj[j,1])); a[i,j]:=a[j,i]; end; for i:=1 to n do begin minn:=abss(sj[i,0]-xx1); if abss(sj[i,0]-x2)<minn then minn:=abss(sj[i,0]-x2); if abss(sj[i,1]-yy1)<minn then minn:=abss(sj[i,1]-yy1); if abss(sj[i,1]-y2)<minn then minn:=abss(sj[i,1]-y2); a[i,0]:=minn; a[0,i]:=minn; end; ss(0); h:=anm*3.14159265358979323846; s1:=abss(x2-xx1)*abss(y2-yy1); zj:=round(s1-h); writeln(zj); end.
原文:https://www.cnblogs.com/sy666/p/12327537.html