POJ-1190-生日蛋糕-DFS(深搜)-枚举-多重剪枝

题目链接:

这个题目非常好,有难度;能够好好的多做做;

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<cmath>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#define LL long long
using namespace std;
int MinArea=1<<30;  //  存最优表面积。
int MinV[30];       //  存第一层到该层最小体积;
int MinA[30];       //  存第一层到该层最小面积。
int N,M;            //  体积,层数。
int area=0;         //  存增在搭建的表面积;
int MaxV(int n,int r,int h)     //  当有n层时。能够有的最大体积;当中r为最大半径,h为最大高度;
{
    int v=0;
    for(int i=0;i<n;i++) v+=(r-i)*(r-i)*(h-i);
    return v;
}
void dfs(int v,int n,int r,int h)
{
    if(n==0){           //  说明一种情况搭建层数已经完毕。
        if(v) return;
        else{
            MinArea=min(MinArea,area);      //  能够搭建,则更新最优解。
            return;
        }
    }
    if(v<=0) return;                    //  体积不够,退出。
    if(MinV[n]>v) return;               //  搭建n层的最小体积比提供的体积大。即无法搭建。退出;
    if(area+MinA[n]>=MinArea) return;   //  当前搭建表面积加上前n层最小的表面积比最优解更大。则能够退出。
    if(h<n||r<n) return;                //  最大半径,或者最大高度比层数还要多。则就说明已经无法继续搭建了。
    if(MaxV(n,r,h)<v) return;           //  这n层能够搭建的最大体积都比提供的体积要小,说明无法按要求搭建;
    for(int rr=r;rr>=n;rr--){       //  从最大半径開始枚举搜索。
        if(n==M) area=rr*rr;        //  底面积;
        for(int hh=h;hh>=n;hh--){   //  从最大高度開始枚举。
            area+=2*rr*hh;          //  搭建的面积更新;
            dfs(v-rr*rr*hh,n-1,rr-1,hh-1);
            area-=2*rr*hh;          //  回溯;
        }
    }
}
int main()
{
    while(~scanf("%d%d",&N,&M)){
        MinV[0]=0;
        MinA[0]=0;
        for(int i=1;i<=M;i++){
            MinV[i]=MinV[i-1]+i*i*i;                    //  前i层最小体积;
            MinA[i]=MinA[i-1]+2*i*i;                    //  前i层最小面积;
        }
        if(MinV[M]>N) printf("0\n");
        else{
            int MaxH=(N-MinV[M-1])/(M*M)+1;             //  底层最大高度。
            int MaxR=sqrt(double(N-MinV[M-1])/M)+1;     //  底层最大半径;
            int area=0;
            MinArea=1<<30;
            dfs(N,M,MaxH,MaxR);
            if(MinArea==1<<30)  printf("0\n");
            else  printf("%d\n",MinArea);
        }
    }
    return 0;
}


 

posted @ 2017-04-28 16:47  gccbuaa  阅读(131)  评论(0编辑  收藏  举报