题目链接:
这个题目很好,有难度;可以好好的多做做;
#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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/wlxsq/article/details/47024825