N久以前写的一个迭代加深和神奇剪枝的搜索,如今我竟然写不出来,悲哀啊!
出答案很简单,但是要AC要加各种神奇的优化,我都写在代码的注释中了啦。
#include<cstdio>
#include<cmath>
using namespace std;
int best = 0xffffff,n,m,minv[25];
void dfs(int i,int ri,int hi,int si,int vi)//剩余层数,上一层半径,上一层高度,当前表面积,剩余蛋糕体积
{
if(i == 0)
{
if(si < best&&vi == 0) best = si;
return;
}
if(vi < minv[i]) return;//比至少剩的体积还小,做不成蛋糕
if(vi/(2*ri)+si > best) return;//剩余体积/(2*上一层半径) = 可能的最小侧面积,加上已经有的面积,还比最优解大,那么没有更优的解
for(int j = ri-1; j >= i; j--)
{
if(i == m) si = j*j;//最下一层的半径决定了上表面的面积
for(int k = hi-1; k >= i; k--)
dfs(i-1,j,k,si+2*j*k,vi-j*j*k);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i++)//至少剩余的体积,从上往下第i层的半径高度至少为i
{
minv[i] = minv[i-1] + i*i*i;
}
dfs(m,sqrt(n/m),n/(m*m),0,n);//体积/最小高度=最大底面积,开个根号就是最大地面半;体积/(最小底面积半径^2)=地面最大高度
if(best == 0xffffff)
printf("0\n");
else
printf("%d\n",best);
}