1. 程式人生 > >【OI做題記錄】【BZOJ】【SCOI2009】生日快樂

【OI做題記錄】【BZOJ】【SCOI2009】生日快樂

試題編號:BZOJ1024

windy的生日到了,為了慶祝生日,他的朋友們幫他買了一個邊長分別為 X 和 Y 的矩形蛋糕。現在包括windy
,一共有 N 個人來分這塊大蛋糕,要求每個人必須獲得相同面積的蛋糕。windy主刀,每一切只能平行於一塊蛋糕
的一邊(任意一邊),並且必須把這塊蛋糕切成兩塊。這樣,要切成 N 塊蛋糕,windy必須切 N-1 次。為了使得
每塊蛋糕看起來漂亮,我們要求 N塊蛋糕的長邊與短邊的比值的最大值最小。你能幫助windy求出這個比值麼?

輸入描述

包含三個整數,X Y N。1 <= X,Y <= 10000 ; 1 <= N <= 10

輸出描述

包含一個浮點數,保留6位小數。

輸入樣例

5 5 5

輸出樣例

1.800000

試題分析

好久沒有1A了,好開心啊!

①演算法確定 求最小值,這種求極值的題目,大概有幾個思路:DP,貪心,純模擬。 由於N非常的小,所以好像純模擬可以做,確切的說,用深搜。 ②演算法結構 我們發現,既然要分的蛋糕,面積相同,且分的方式只能垂直或者平行。深搜的拓展方式就比較少了。 對於一塊x*y的蛋糕,分成K份,每份的面積是確定的,那麼分的方式就有兩種: 這種情況可以將這個圖再分成兩部分,進行深搜

左部分再分成三份,右部分分成K-3分 另一種分法:
③演算法細則
每種分法都將原來的蛋糕分為兩塊,每一塊最終得到長寬的比,取較大值。 然後兩種分法取較小值。 程式碼
#include<cstdio>
#include<cstdlib>
#include<cstring>
int x,y,n;
double mymax(double x,double y)
{
	return x>y?x:y;
}
double mymin(double x,double y)
{
	return x<y?x:y;
}
double done(double x,double y,int n)
{
	if(n==1)return mymax(x,y)/mymin(x,y);
	double ans=999999999999;
	for(int i=1;i<n;i++)
	{
		double xx=mymax(done(x,y/n*i,i),done(x,y/n*(n-i),n-i));
		double yy=mymax(done(x/n*i,y,i),done(x/n*(n-i),y,n-i));
		ans=mymin(ans,mymin(xx,yy));
	}
	return ans;
}
int main()
{
	scanf("%d %d %d",&x,&y,&n);
	printf("%.6lf",done(x,y,n));
}