1. 程式人生 > >P1378 油滴擴展

P1378 油滴擴展

clas sin 半徑 兩個 邊界 int 圓的面積 輸出 sqrt

題目描述

在一個長方形框子裏,最多有N(0≤N≤6)個相異的點,在其中任何一個點上放一個很小的油滴,那麽這個油滴會一直擴展,直到接觸到其他油滴或者框子的邊界。必須等一個油滴擴展完畢才能放置下一個油滴。那麽應該按照怎樣的順序在這N個點上放置油滴,才能使放置完畢後所有油滴占據的總體積最大呢?(不同的油滴不會相互融合)

註:圓的面積公式V=pi*r*r,其中r為圓的半徑。

輸入輸出格式

輸入格式:

第1行一個整數N。

第2行為長方形邊框一個頂點及其對角頂點的坐標,x,y,x’,y’。

接下去N行,每行兩個整數xi,yi,表示盒子的N個點的坐標。

以上所有的數據都在[-1000,1000]內。

輸出格式:

一行,一個整數,長方形盒子剩余的最小空間(結果四舍五入輸出)

輸入輸出樣例

輸入樣例#1: 復制
2
20 0 10 10
13 3
17 7
輸出樣例#1: 復制
50


很不錯的一題,看到N的範圍不難想到搜索……
註意搜索第i個點時,計算r【i】的過程,先枚舉和邊界的距離,再枚舉和其他已經計算過的點的距離。
AC代碼如下:
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const double P=3.1415926535;
bool use[7];
int n;
double r[7],x[7],y[7],a,b,c,d,ss,ans;
void dd(int nd)
{
    double xx=min(abs(a-x[nd]),abs(c-x[nd]));
    double yy=min(abs(b-y[nd]),abs(d-y[nd]));
    r[nd]=min(xx,yy);
    for(int i=1;i<=n;i++)
    if(i!=nd&&use[i])
    {
        double dist=sqrt((x[i]-x[nd])*(x[i]-x[nd])+(y[i]-y[nd])*(y[i]-y[nd]));
        r[nd]=min(r[nd],max(dist-r[i],0.0));
    }
    return;
}
void dfs(int now,double sum)
{
    if(now>n){if(ans<sum) ans=sum;return;}
    for(int i=1;i<=n;i++)
    if(!use[i]) {
     dd(i);use[i]=1;dfs(now+1,sum+r[i]*r[i]*P);use[i]=0;
    }
    return;
}
int main()
{
    scanf("%d",&n);
    scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    ss=abs(a-c)*abs(b-d);
    for(int i=1;i<=n;i++)
    scanf("%lf%lf",&x[i],&y[i]);
    dfs(1,0);
    printf("%d",int(ss-ans+0.5));
    return 0;
}

P1378 油滴擴展