您的位置:首页 > 其它

POJ 1190 生日蛋糕

2016-07-20 08:47 344 查看
主函数尽量少写,都放到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
>v) return 2;//若从n层起的最小体积都大于所需要搭建的体积,则无法达到v,返回
if(minA
+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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: