璟雯院

珺璟如晔,雯华若锦

用户工具

站点工具


icpc:problems:生日蛋糕
problems
名称生日蛋糕
题目编号168
题目链接acwing.com/…
来源Acwing
算法分类搜索, DFS, 剪枝, 剪枝_例题
难易程度一般般

生日蛋糕

想法

规定第1层为最低层,则由于每一层都需要比上一层要大,故第1层的$r$与$h$最小值均为$m$,可以得出第$x$层的$r$与$h$的最小值均为$m - x + 1$。

此题最重要的剪枝为对未来的最优性剪枝:假设当前枚举第x层的蛋糕,我们可以得出后$x \to m$层的体积为 $n - v = \sum^{m}_{i=x} h_i * r_i^2 $,表面积为 $2 * \sum^{m}_{i=x} h_i * r_i$。

假设当前第x层蛋糕的半径为$r_x$,由题意可知,后续的$r_i$均比$r_x$小。对后续的表面积公式进行放缩可得:

$$ 2 * \sum^{m}_{i=x} h_i * r_i = \frac{2}{r_x} * \sum^{m}_{i=x} h_i * r_i * r_x \geq \frac{2}{r_x} * \sum^{m}_{i=x} h_i * r_i * r_i = \frac{2 * (n - v)}{r_x}$$

所以我们可以预估出后续最小的表面积为 $\frac{2 * (n - v)}{r_x}$,当 $s + \frac{2 * (n - v)}{r_x} > ans$时,说明当前搜索的情况不是最优的,需要对其进行剪枝。

代码实现

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
 
int n, m, ans = 0x7f7f7f7f;
 
void DFS(int x, int s = 0, int v = 0, int front_r = sqrt(n), int front_h = n) {
	if(x > m) {
		if(v == n)
			ans = ans > s ? s : ans;
		return ;
	}
	for (int r = min((int)floor(sqrt(n-v)), front_r-1); r >= m-x+1; r--){
		if(2*(n-v)/r + s > ans) break;
		for (int h = min((int)floor(1.0*(n-v)/(r*r)), front_h-1); h >= m-x+1; h--) {
			DFS(x + 1, s + 2 * r * h + (x == 1 ? r * r : 0), v + r * r * h, r, h);
		}
	}
	return ;
}
 
int main() {
	scanf("%d %d", &n, &m);
 
	DFS(1);
 
	printf("%d", ans == 0x7f7f7f7f ? 0 : ans);
 
	return 0;
}
/app/www/public/data/pages/icpc/problems/生日蛋糕.txt · 最后更改: 2023/07/09 03:51 由 温婕莺