Question:
Create a birthday cake with a volume of N π (n <= 10000) on the m (M <= 20) layer. Each layer is a cylinder.
Set the number of I (1 <= I <= m) layers from bottom to top to a column with Ri radius and HI height. When I <m, RI> RI + 1 and HI> Hi + 1 are required.
To minimize the cost of using cream on a cake, we hope that the surface of the cake (except the bottom of the bottom layer) has the minimum area Q.
Set q = s π
Program the N and M given to find out the cake production solution (appropriate RI and HI values) to minimize S.
(All data except Q is a positive integer)
Analysis:
The surface area is only related to the circular area on the bottom and the area on the side of each layer.
Q = s π
S = R1 * R1 + 2 * sigma (Ri * Hi (1 <= I <= m ))
N = sigma (Ri * Hi (1 <= I <= m ))
Status (I, RI, hi, Si-1, Di-1) Transfer ---> (I + 1, RI + 1, hi + 1, Si, DI)
Enumeration variable RI and HI. To reduce the number of states, we need to reduce the enumerated range of RI and HI.
There must be:
M-I <= RI + 1 <ri
M-I <= Hi + 1
Pruning 1:
Pre-Calculation
Mins [I] indicates the minimum number of s to be used from top to bottom layers to layer I
Minn [I] indicates the minimum n to be used from the top to the bottom layer to the I layer.
Then there is pruning:
Si-1 + mins [M-I]> = Best // optimum pruning
Di-1 + Minn [M-I]> = N // feasible pruning
Pruning 2:
Side area increased from K-layer to m-Layer
Si-1 + 2 * (N-Di-1)/RI> = Best // optimum pruning
Pruning 3:
If Ri is enumerated first, the upper bound of Hi maxh = min (hi-1, n-Si-1-Minn [M-i-1])/(Ri * RI) // feasibility pruning
// Enumerate hi first ..
#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <string>#include <set>#include <map>using namespace std;#define min(a,b) (a) <(b) ? (a):(b)#define INF 0x3f3f3f3fint minN[25], minS[25];int N, M, Min;void init(){ int i; minN[0] = minS[0] = 0; for(i=1; i<=21; ++i) { minS[i] = minS[i-1] + 2 * i * i; minN[i] = minN[i-1] + i * i * i; }}void dfs(int k, int r, int h, int sums, int sumv){ if(k==M){ if(sumv == N && sums < Min) { Min = sums; } return ; } if(sums + minS[M-k] > Min ||sumv + minN[M-k] > N||2*(N-sumv)/r + sums >= Min) return ; for(int i=r-1; i>=M-k; --i) { if(k==0) sums = i * i; int maxH = min( h-1, (N-sumv-minN[M-k-1])/(i*i) ); for(int j=maxH; j>=M-k; --j) dfs(k+1, i, j, sums + 2 * i * j, sumv + i * i * j); }}int main(){ init(); while(cin>>N>>M) { Min = INF; dfs(0, N, N, 0, 0); //K, R, H, SUMS, SUMV if(Min<INF) cout<<Min<<endl; else cout<<0<<endl; } return 0;}