题解 P1378 【油滴扩展】

题面

在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)

注:圆的面积公式V=pi*r*r,其中r为圆的半径。

题意

再规定的矩形内可以滴几个油滴,油滴滴的顺序不做要求,但是油滴滴的位置有要求。另外油滴滴在矩形内会一直扩展,直至碰着另一个油滴,或者撞到边界。

求矩形盒子内滴完油滴剩余的最小空间。

题解

我的思路很不好,为防误导,直接讲这题跑到\(0ms\)大神的思路和代码。

代码

#include<stdio.h>
#include<math.h>
#define PI 3.1415926

int n,vis[7];
double A[7][2],x,y,x2,y2,R[7],max,dis[7][7];

double abss(double a){return a>0.0?a:-a;}

void dfs(int step,double s)
{//准备放置第step个油滴,放置前面积为s
    int k,i;
    double r=0;//准备放置的油滴的扩散半径 

	if(step==n+1)//放完 
        max=s>max?s:max;
    else
      for(k=1;k<=n;k++) if(!vis[k])
      {
          //矩形和已放置的油滴约束了r的大小 
          r=abss(y2-A[k][1]);
          
          if(r>abss(x2-A[k][0])) r=abss(x2-A[k][0]);
          if(r>abss(y-A[k][1])) r=abss(y-A[k][1]);
          if(r>abss(x-A[k][0])) r=abss(x-A[k][0]);
          
          for(i=1;i<=n;i++) if(vis[i])
              if(r>dis[k][i]-R[i]) r=dis[k][i]-R[i];
          
          r=r<0?0:r;//注意r不能为负 
          
          vis[k]=1;R[k]=r;
          dfs(step+1,s+PI*r*r);
          vis[k]=0;R[k]=0.0;
	  }
}

int main(void)
{
    int i,j;
    scanf("%d%lf%lf%lf%lf",&n,&x,&y,&x2,&y2);

	for(i=1;i<=n;i++) scanf("%lf%lf",&A[i][0],&A[i][1]); 
    
    //预处理出油滴间距dis 
    for(i=1;i<=n;i++) for(j=1;j<i;j++) if(i!=j)
        dis[i][j]=dis[j][i]=sqrt((A[i][0]-A[j][0])*(A[i][0]-A[j][0])+
            (A[i][1]-A[j][1])*(A[i][1]-A[j][1]));
    
    dfs(1,0.0);
    
    double S=abss(x-x2)*abss(y-y2);//矩形面积 
    printf("%.0lf",S-max);
    
    return 0;
}
posted @ 2018-11-07 09:41  Chicago_01  阅读(199)  评论(0编辑  收藏  举报