由於深度一定(m),所以使用深度優先搜尋,自上而下的設定蛋糕序號,最頂層的為第1層,……,最底層的蛋糕為第m層,很明顯滿足題目條件的前i層的(從頂層(也就是編號為1的層)開始計數)最小面積mins[i]和體積minv[i]是在該層的半徑以及高度都為i時取得,如果採用一般的神搜肯定會逾時,所以這題還需要剪枝,剪枝條件有(從m層向上搜,假設前dep層的體積為sumv,面積為sums,當前所得的最小面積為best):
1> 因為前dep層的體積為sumv,如果剩下的幾層的體積都取最小可能值,總體積還是比n大,那麼則說明前dep層的方案不可行,所以可以剪枝(剪枝條件為:sumv+minv[dep-1]>n)
2> 因為前dep層的面積為sums,如果剩下的幾層的面積都取最小可能值,所得的面積和比已經得到的所求的最小面積best大,也可以進行剪枝(剪枝條件為:sums+mins[dep-1]>best)
3> 因為前dep層的體積為sumv,那麼剩餘的m-dep層的體積滿足:n-sumv=(h[k]*(r[k]^2)+……+h[m]*(r[m]^2)) (k=dep+1,……,m)
而剩餘部分的表面積滿足:lefts=2*(r[k]*h[k]+……+r[m]*h[m])>2*(n-sumv)/r[dep] (k=dep+1,……,m)
顯然有上述不等式lefts=best-sums>2*(n-sumv)/r,即2*(n-sumv)/r+sums<best,所以當2*(n-sumv)/r[i]+sums>=best時也可以進行剪枝.
#include <stdio.h>#include <stdlib.h>int ans;int minv[25],mins[25];int n,m;int Min(int a, int b){return a > b ? b : a;}void dfs(int sumv, int sums, int now, int r, int h){int i, j, realh;if (now == 0){if (sumv == n && sums < ans){ans = sums;return;}}if (sumv + minv[now - 1] > n || sums + mins[now - 1] > ans || 2 * (n - sumv) / r + sums >= ans){return;}for (i = r - 1; i >= now; -- i){if (now == m){sums = i * i;}realh = Min((n - minv[now - 1] - sumv) / (i * i), h -1);for (j = realh; j >= now; -- j){dfs(sumv + i * i * j, sums + 2 * i * j, now - 1, i, j);}}}int main(){int i, j;scanf("%d", &n);scanf("%d", &m);minv[0] = 0;mins[0] = 0;//the min r = i and h = ifor (i = 1; i <= m; ++ i){minv[i] = minv[i - 1] + i * i * i;mins[i] = mins[i - 1] + 2 * i * i;}ans = 999999;dfs(0, 0, m, n + 1, n + 1);if (ans == 999999){printf("0\n");}elseprintf("%d\n", ans);return 0;}