生日蛋糕

生日蛋糕

以下所有变量都是在正整数范围中,要制作一个体积为(npi)的蛋糕,每一层都是一个圆柱体,从上往下数,第i层蛋糕的半径为(r_i),高度(h_i),求蛋糕外表面的面积的最小值/(pi)(忽略下底面),(nleq 10000,mleq 20)

m很小,考虑搜索,下面给出本题的结论。

  1. 搜索框架:自下而上搜索,枚举每一层蛋糕的高度和底面半径。

  2. 显然带(pi)是不好研究的,但是最终的体积和面积每一项都会有(pi),于是可以将之提出来,接下来所有式子都是已经提出了(pi)

  3. 显然非侧面积就是底下的蛋糕的上表面积,刚开始搜索时就累加即可。

  4. 考虑每一层蛋糕的高度和半径的枚举范围,设d为当前为第几层(从上往下数),前面已经确定了体积v,容易有(r_din[d,min(r_{d+1},sqrt{n-v})])((r^2hleq n-v,h_{min}=1Rightarrow rleqsqrt{n-v})),同样的道理有(h_din[d,min(h_{d+1},frac{n-v^2}{r^2}))

  5. 考虑d层内的最小体积和面积,显然当半径和高度都为1的时候达到最小,于是有最小体积(sum_{i=1}^di^3),最小面积(2sum_{i=1}^di^2),于是当已经确定的体积加上未确定的最小体积大于n那么可以return,如果已经确定的面积加上上面最小表面积大于等于最优解,return.

  6. 考虑玄学剪枝,有(2sum_{i=1}^dh_ir_i=frac{2}{r_{d+1}}sum_{i=1}^dh_ir_ir_{d+1}geq frac{2}{r_{d+1}}sum_{i=1}^dh_ir_i^2geq frac{2(n-v)}{r_{d+1}})
    于是已经确定的表面积加上最后一个式子大于等于最优解,那么return。

参考代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int n,m,ans(intmax),r[50],h[50];
void dfs(int,int,int);
il int powsum(int),
	cubesum(int);
int main(){
	scanf("%d%d",&n,&m);
	h[m+1]=r[m+1]=intmax,dfs(m,0,0);
	printf("%d",ans);
	return 0;
}
il int cubesum(int n){
	return pow(n*(n+1)/2,2);
}
il int powsum(int n){
	return n*(n+1)*(2*n+1)/6;
}
void dfs(int d,int v,int s){
	if(v+cubesum(d)>n)return;
	if(s+powsum(d)*2>=ans)return;
	if(s+2*(n-v)/r[d+1]>=ans)return;
	if(!d){if(v==n)ans=s;return;}
	int rr(min(r[d+1]-1,(int)sqrt(n-v)));
	for(int i(rr),j;i>=d;--i)
		for(j=min(h[d+1]-1,(n-v)/(i*i));j>=d;--j)
			r[d]=i,h[d]=j,dfs(d-1,v+i*i*j,s+2*i*j+(d==m)*i*i);
}

原文地址:https://www.cnblogs.com/a1b3c7d9/p/11276451.html