POJ1190 生日蛋糕(DFS)

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);
}
点赞