泰国佛塔

来源:互联网 发布:测试手机性能软件 编辑:程序博客网 时间:2024/04/26 06:14

描述

泰囧,大家应该都看过。不知道大家有没有注意到宝宝虔诚祈福的寺庙里的金灿灿的佛塔。      

众所周知,泰国佛塔外面是贴金的,而且金箔过一段时间需要修补。泰国经济自上世纪末就不景气,贴金的开支对于寺庙来说也是个比较大的负担。          

这里请同学来帮助寺庙设计下佛塔的模型,以使佛塔的外表面(最下层的下底面除外)的面积最小。从而节省金箔开支。      

这里抽象佛塔形状为,一层层的圆柱体,自底向上直径递减。制作一个体积为Nπ的M层佛塔。设从下往上数第i(1 <= i <= M)层佛塔是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri> Ri+1且Hi> Hi+1。令外表面面积为Q=Sπ。      

请编程,对于给出的N和M,找出佛塔的制作方案(适当的Ri和Hi的值),使S最小。(除Q外,以上所有数据皆为正整数)

输入
包括若干行。每行包括两个整数N(N <= 10000)、M(M <= 20),代表一组测试数据。分别表示待建造的佛塔的体积为Nπ,和佛塔的层数为M。
输出
对于每组测试数据,输出占一行:一个正整数S(若无解则S = 0)。
样例输入
100 2
27 15
样例输出
68
0

感谢周洋师弟的帮助。


#include <iostream>#include <algorithm>#include <cstring>#include <cmath>using namespace std;/*考虑用m层佛塔去凑n体积,考虑几种剪枝;*/const int MAX_N = 10010;int min_v[MAX_N],min_s[MAX_N];//min_x[m]表示m层佛塔所具有的最小的体积/侧面积;int MAX_NRH_Store[25][25][25];//储存MAX_V_NRH函数的返回值;int mins = 1<<30;//记录最小侧面积;int N,M;//n为总体积,m为总层数int MAX_V_NRH(int m,int r,int h){//计算底层半径为r,底层高度为h的n层佛塔的最大体积;    if(MAX_NRH_Store[m][r][h])//省去重复计算;        return MAX_NRH_Store[m][r][h];    int v = 0;    for(int i = 0;i < m;i++){        v += (r-i)*(r-i)*(h-i);    }    return v;}int dfs(int n,int m,int s,int r,int h){//深搜函数,用m层佛塔凑出体积n,底层半径r,底层高度h,当时侧面积之和为s;    if(m==0){//层数用完,若剩余体积为0,完成,返回0;        if(n==0)            mins = min(s,mins);        return 0;    }    if(min_v[m] > n || min_s[m] + s >= mins){//体积或侧面积超出;        return 0;    }    if(MAX_V_NRH(m ,r ,h) < n){//剩下m层凑不出体积n;        return 1;    }    //剪枝完毕,开始通过循环进行求解    for(int i = r;i >= m;i--){        for(int j = h;j >= m;j--){            if(m == M)//剩余层数为全部M层,需考虑底面积;            {                if(dfs(n - i * i * j,m - 1,s + i * i + 2 * i * j,i - 1,j - 1))                    break;//跳出本层循环;            }            else            {                if(dfs(n - i * i *j,m - 1,s + 2 * i * j,i - 1,j - 1))                    break;            }        }    }    return 0;}int main(){    memset(MAX_NRH_Store,0,sizeof(MAX_NRH_Store));    while(cin >> N >> M){        mins = 1<<30;        for(int i = 0;i < M; i++){            //无需初始化,全局变量声明后自动赋值为0;            min_v[i+1] = min_v[i] + (i+1)*(i+1)*(i+1);            min_s[i+1] = min_s[i] + 2*(i+1)*(i+1);        }        int max_r = sqrt(double(N - min_v[M - 1])/M) + 1;        int max_h = (N - min_v[M - 1])/(M * M) + 1;        dfs(N, M, 0, max_r, max_h);        if(mins == 1 << 30)            cout<<0<<endl;        else            cout<<mins<<endl;    }}






0 0
原创粉丝点击