\(\mathcal{Description}\)
July 17 is \ (Mr.W \) birthday, \ (the THU-the ACM \) for this purpose to create a volume of \ (M \) layer birthday cake, are each a cylinder. Set up from under the number \ (I \) \ ((. 1 \ Leq I \ Leq M) \) layer cake with a radius \ (R_i \) , height \ (H_i \) cylinder. When (i \ <M \) , the required \ (R_i> R_ {i + 1} \) and \ (H_i> H_ {i + 1} \) due to rubbed cream cake, cost reduction is possible, we hope (lowermost layer under the bottom surface excluding) the area of the outer surface of the cake \ (Q \) minimum. Order \ (Q = S \ PI \) , to program a given \ (N \) and \ (M \) , to find the cake recipe programs (appropriate \ (R_i \) and \ (H_i \) of value), so that \ (S \) minimum. (Except \ (Q \) , all the above data are all positive integer)
\(\mathcal{Input\ Format}\)
There are two rows, the first row \ (N \) , represents the volume of the cake to be made to \ (N \ PI \) ; a second behavior \ (M \) , represents the number of layers of cake \ (M \) .
\(\mathcal{Output\ Format}\)
Only one row is a positive integer \ (S \) (if no solution is \ (S = 0 \) ).
\(\mathcal{DataSize\ Agreement}\)
\ (1 \ leq N \ leq 20000, 1 \ leq M \ leq 15 \) .
\(\mathcal{Solution}\)
First is difficult to think of search, direct search will be very slow, considering to add some pruning:
Feasibility of pruning: the current level plus the smallest volume than \ (n-\) large, is not feasible;
Optimal Pruning:
1, plus the minimum current area side than the recording layer at the area of \ (ANS \) is large, the kinds of programs that will certainly not optimal;
2, if the lower layer side of the area corresponding to the remaining volume plus the current area is not less than \ (ANS \) , this solution is not optimal (must be greater than equal to the radius of the next layer because of not taking the current \ (R & lt \) )
A pretreatment tips of the minimum volume of each layer, and the minimum area
\(\mathcal{Code}\)
#include <bits/stdc++.h>
#define LL long long
#define reg register
using namespace std;
const int kMax = 21;
const int inf = 0x7f7f7f7f;
int mins[kMax], minv[kMax];
int N, M, Ans = inf;
void dfs(int v, int s, int p, int r, int h) {
if (p == 0) {
if (v == N) Ans = min(Ans, s);
return ;
}
if (v + minv[p - 1] > N) return ; // 可行性剪枝
if (s + mins[p - 1] > Ans) return ; // 最优性剪枝
if (s + (N - v) / r * 2 >= Ans) return ; //最优性剪枝
for (reg int i = r - 1; i >= p; --i) {
if (p == M) s = i * i;
int minh = min(h - 1, (N - v - minv[p - 1]) / (i * i));
for (reg int j = minh; j >= p; --j)
dfs(v + i * i * j, s + 2 * i * j, p - 1, i, j);
}
}
int main() {
scanf("%d%d", &N, &M);
for (reg int i = 1; i <= 20; ++i) mins[i] = mins[i - 1] + i * i, minv[i] = minv[i - 1] + i * i * i;
dfs(0, 0, M, N + 1, N + 1);
printf("%d\n", (Ans == inf ? 0 : Ans));
return 0;
}