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;
}

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

时间: 2024-11-06 09:52:57

POJ-1190-生日蛋糕-DFS(深搜)-枚举-多重剪枝的相关文章

POJ 1190 生日蛋糕 DFS

生日蛋糕 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18225   Accepted: 6486 Description 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱.当i < M时,要求Ri > Ri+1且Hi > Hi+1. 由于要在蛋糕上抹奶油,为尽可能

POJ 1190 生日蛋糕

POJ 1190 生日蛋糕 dfs + 剪枝 Description: 要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱.当i < M时,要求Ri > Ri+1且Hi > Hi+1. 由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小. 令Q = Sπ 请对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小. (除Q外,以上所有

CodeM美团点评编程大赛初赛B轮 黑白树【DFS深搜+暴力】

[编程题] 黑白树 时间限制:1秒 空间限制:32768K 一棵n个点的有根树,1号点为根,相邻的两个节点之间的距离为1.树上每个节点i对应一个值k[i].每个点都有一个颜色,初始的时候所有点都是白色的. 你需要通过一系列操作使得最终每个点变成黑色.每次操作需要选择一个节点i,i必须是白色的,然后i到根的链上(包括节点i与根)所有与节点i距离小于k[i]的点都会变黑,已经是黑的点保持为黑.问最少使用几次操作能把整棵树变黑. 输入描述: 第一行一个整数n (1 ≤ n ≤ 10^5) 接下来n-1

A Knight&#39;s Journey(DFS)深搜

A Knight's Journey Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33634 Accepted: 11450 Description Background The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey around

hdu1010-Tempter of the Bone DFS深搜入门题+奇偶剪枝

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 69699    Accepted Submission(s): 19176 Problem Description The doggie found a bone in an ancient maze, which fascinated him a

DFS深搜-Red and Black

深搜,从一点向各处搜找到所有能走的地方. Problem Description There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on

dfs深搜

dfs深搜 什么是深搜? 百度百科:按照一定的顺序.规则,不断去试探,直到找到问题的解,试完了也没有找到解,那就是无解,试探时一定要试探完所有的情况(实际上就是穷举) 个人理解:暴力穷举每一种状态 它有什么好处? 容易理解 骗分利器 好写 它有什么弊端? 慢.毕竟是穷举每一种状态 一搜到底.对于递归次数非常多的话,dfs会非常浪费时间,甚至有可能会爆栈 如何实现? 算法流程图如下: #include <iostream> #include <cstdio> void dfs(int

NYOJ 293 Sticks 【深搜】+【剪枝】

这是一道让人泪奔的题,它深刻的说明了什么是剪枝,哪怕是再小的一个细节,一旦递归规模增大都会引发巨大的时间消耗,真是神题~ Sticks 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the

poj1190 生日蛋糕(深搜+剪枝)

题目链接:poj1190 生日蛋糕 解题思路: 深搜,枚举:每一层可能的高度和半径 确定搜索范围:底层蛋糕的最大可能半径和最大可能高度 搜索顺序:从底层往上搭蛋糕,在同一层尝试时,半径和高度都是从大到小试 剪枝: ①已建好的面积已经超过目前求得的最优表面积,或者预见到搭完后面积一定会超过目前最优表面积,则停止搭建(最优性剪枝) ②预见到再往上搭,高度已经无法安排,或者半径无法安排,则停止搭建(可行性剪枝) ③还没搭的那些层的体积,一定会超过还缺的体积,则停止搭建(可行性剪枝) ④还没搭的那些层的