POJ 1190 生日蛋糕

来源:互联网 发布:大唐双龙传知乎 编辑:程序博客网 时间:2024/05/16 04:01
主函数尽量少写,都放到dfs里面去
#include<iostream>#include<cstdio>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int maxn=20+5;int minV[maxn],minA[maxn],maxV[maxn];int area,bestarea=100000000;int m,t;int maxVforNRH(int n,int r,int h)//求出从n从到最上面一层的最大体积{    int ans=0;    for(int i=n;i>=1;i--){        ans+=r*r*h;        r--,h--;    }    return ans;}int dfs(int v,int n,int r,int h){    if(n==0){        if(v)            return 0;        else{            bestarea=min(bestarea,area);            return 1;        }    }    if(v<=0) return 7;//如果上升一层后,v为负数,则返回,原因是上一层的体积太大,超出题目所给体积要求    if(minV[n]>v) return 2;//若从n层起的最小体积都大于所需要搭建的体积,则无法达到v,返回    if(minA[n]+area>=bestarea) return 3;//如果现有的表面积加上从n层到最上面一层的最小表面积都大于最优表面,则返回    if(h<n||r<n) return 4;//h,r没上升一层最起码-1,若还有n层,但h,r却小于n,则不可能达到要求,返回    if(v>maxVforNRH(n,r,h)) return 5;//如果所要搭建的面积比可以搭建的最大面积还要大,则无法达到所求面积,返回    for(int i=r;i>=n;i--)    {        if(n==t) area=i*i;        for(int j=n;j<=h;j++)//从小到大枚举是为了下面的break语句        {            area+=2*i*j;            int ok=dfs(v-i*i*j,n-1,i-1,j-1);//因为j是从小到枚举的,所以v是从大到小的,那么如果返回的是2,则说明所需搭建的最小体积都比要求的体积大,再往下枚举只会v越来越小,越不符合要求,所以下面可以break;            area-=2*i*j;            if(ok==2) break;        }    }    return 6;}int main(){    scanf("%d%d",&m,&t);    minV[0]=0;minA[0]=0;    for(int i=1;i<=t;i++){        minV[i]=minV[i-1]+i*i*i;        minA[i]=minA[i-1]+2*i*i;    }    if(m<minV[t]) printf("0\n");    else{        int maxr,maxh;        maxh=(m-minV[t-1])/(t*t)+1;        maxr=sqrt((double)(m-minV[t-1])/t)+1;        area=0;        bestarea=(1<<30);        dfs(m,t,maxr,maxh);        if(bestarea==(1<<30))            printf("0\n");        else            printf("%d\n",bestarea);    }    return 0;}

0 0
原创粉丝点击