油滴擴展
【問題描述】
在一個長方形框子裏,最多有N(0≤N≤6)個相異的點。在其中任何一個點上放一個很小的油滴,那麼這個油滴會一直擴展,直到接觸到其他油滴或者框子的邊界。必須等一個油滴擴展完畢才能放置下一個油滴。那麼應該按照怎樣的順序在這N個 點上放置油滴,才能使放置完畢後所有油滴佔據的體積最大呢?(不同的油滴不會相互融合)
注:圓的面積公式 V=pi*r*r,其中r爲圓的半徑。
【輸入】
第一行一個整數N。
第二行爲長方形邊框一個頂點及其對角頂點的座標,x , y , x’, y’。
接下去N行,每行兩個整數xi,yi,表示盒子內N個點的座標。
以上所有的整數都在[-1000,1000]內。
【輸出】
一行,一個整數,長方形盒子剩餘的最小空間(結果四捨五入輸出)。
【輸入樣例】
2
0 0 10 10
3 3
7 7
【輸出樣例】
50
哎,今天的測試成績實在是太差,這樣的情況已經持續恆久了,離比賽沒剩幾天,我可不想然我自己後悔,我必須努力衝刺了……加油!!我一定能行!!
廢話也不多說了,直接進入正題吧……
這道題n很小,所以我們可以直接用裸的dfs,具體實現就不說了,看這篇文章的都是大神,我就說一下注意事項吧
注意:
1.n有可能爲0
2.可能存在折樣一種情況,即,當前點已經在一個油滴擴展後的範圍之內,也可以表達成,這個油滴將要擴展的半徑爲負。這時我們就要把這樣的半徑賦值爲0
3.四捨五入的有關實現一定要注意,尤其是當n=0時,別忘了!
本若菜在寫這題之前忘了如何用四捨五入的函數了,所以手打了一個,見笑了……
+++++++++++++++++++++++++++++代碼如下++++++++++++++++++++++++++++++++++++++++
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define pi 3.1415926
using namespace std;
double d[15][15],ans,dis,r[15];
int n,x[15],y[15],b[15];
int ok()
{
for(int i=2;i<=n+1;i++)
if(!b[i])return 0;
return 1;
}
double mmin(double x,double y,double z,double p)
{
double num=min(x,y);
num=min(num,z);
num=min(num,p);
return num;
}
void dfs()
{
if(ok()){dis=max(dis,ans);return;}
for(int i=2;i<=n+1;i++)
if(!b[i])
{
double minc=mmin(abs(x[i]-x[0]),
abs(x[i]-x[1]),
abs(y[i]-y[0]),
abs(y[i]-y[1]));
for(int j=2;j<=n+1;j++)
if(j!=i&&b[j])
minc=min(minc,d[i][j]-r[j]);
if(minc<0)minc=0;
b[i]=1;ans+=(minc*minc);
r[i]=minc;
dfs();
b[i]=0;ans-=(minc*minc);r[i]=0;
}
}
int main()
{
scanf("%d",&n);
cin>>x[0]>>y[0]>>x[1]>>y[1];
if(n==0)
{
ans=abs(x[0]-x[1])*abs(y[0]-y[1]);
if(ans-(int)ans<0.5)ans=floor(ans);
else ans=floor(ans)+1;
cout<<(int)ans;
return 0;
}
for(int i=2;i<=n+1;i++)
cin>>x[i]>>y[i];
for(int j=2;j<=n+1;j++)
for(int i=2;i<=n+1;i++)
if(i!=j)
d[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])
+(y[i]-y[j])*(y[i]-y[j]));
dfs();
ans=abs(x[0]-x[1])*abs(y[0]-y[1])-pi*dis;
if(ans-floor(ans)>=0.5)ans=floor(ans)+1;
else ans=floor(ans);
cout<<ans;
return 0;
}
由於對於實型的操作較弱,下一篇文章將介紹一下對於實型的那些操作……