码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-07-23 17:48:12      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:poj1190   dfs深搜   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;
}


 

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:poj1190   dfs深搜   dfs   生日蛋糕   

原文地址:http://blog.csdn.net/wlxsq/article/details/47024825

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!