1. 程式人生 > >題解 P1378 【油滴擴展】

題解 P1378 【油滴擴展】

dfs efi span void [1] == 一個 lin for

題面

在一個長方形框子裏,最多有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;
}

題解 P1378 【油滴擴展】