1. 程式人生 > >[NOI1999]生日蛋糕

[NOI1999]生日蛋糕

div ans p12 最小 都是 蛋糕 tro class 枚舉

題目:洛谷P1731、Vijos P1297、codevs1710。

題目大意:讓你做一個體積為$N\pi$的每層都是圓柱的蛋糕,m層,且從下到上每層的高度和半徑都不超過下面一層的,且是整數。

設表面積Q=$S\pi$,問你最小的S是多少(不可能輸出0)。

解題思路:搜索即可。

首先發現此題與$\pi$沒什麽關系,可以直接消去,我們忽略即可。

以下所講的表面積體積均忽略$\pi$。

註意以下三種剪枝:

①當前表面積加上上面幾層的最小表面積大於當前答案則退出。

②當前體積加上上面幾層的最小體積大於N則退出。

③當前剩余體積全部做成與上一層半徑相同的蛋糕,表面積大於當前答案則退出。

然後倒著枚舉半徑和高即可(倒著搜總會快那麽一丁點)。

然後就完美地AC了。

C++ Code:

#include<cstdio>
#include<cmath>
int n,m,mv[16],ms[16],ans=0x3fffffff;
void dfs(int now,int s,int v,int preh,int prer){
	if(!now){
		if(v==n&&ans>s)ans=s;
		return;
	}
	if(s+ms[now]>ans||v+mv[now]>n||s+2*(n-v)/prer>ans)return;
	for(int r=prer-1;r>=now;--r){
		if(now==m)s=r*r;
		for(int h=preh-1;h>=now;--h)
		dfs(now-1,s+2*r*h,v+r*r*h,h,r);
	}
}
int main(){
	scanf("%d%d",&n,&m);
	ms[0]=ms[0]=0;
	for(int i=1;i<=m;++i)
	mv[i]=mv[i-1]+i*i*i,ms[i]=ms[i-1]+((i*i)<<1);
	dfs(m,0,0,n,(int)(sqrt(n)+1e-9));
	printf("%d\n",(ans==0x3fffffff)?0:ans);
	return 0;
}

[NOI1999]生日蛋糕