zoukankan      html  css  js  c++  java
  • 洛谷 P1731 生日蛋糕

    题目背景

    7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为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外,以上所有数据皆为正整数)

    题目描述

    输入输出格式

    输入格式:

     

    有两行,第一行为N(N<=20000),表示待制作的蛋糕的体积为Nπ;第二行为M(M<=15),表示蛋糕的层数为M。

     

    输出格式:

     

    仅一行,是一个正整数S(若无解则S=0)。

     

    输入输出样例

    输入样例#1:
    100
    2
    
    输出样例#1:
    68
    思路:搜索+剪枝。
    错因:一开始只加了可行性剪枝,拿到了60分,后来才知道还有最优化剪枝。
    60分的可行性剪枝:
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,m,ans=0x7f7f7f7f,sal,val,use[16];
    struct nond{
        int r,h;
    }v[16];
    void dfs(int now){
        if(val>n)    return ;
        if(sal+v[1].r*v[1].r>=ans)    return ;
        if(now>m&&val<n)    return ;
        if(now>m&&val==n){
            ans=sal+v[1].r*v[1].r;
            return ;
        }
        for(int i=v[now-1].h-1;i>=m-now+1;i--){
            for(int j=m-now+1;j<v[now-1].r;j++){
                v[now].h=i;
                v[now].r=j;
                val+=j*j*i;
                sal+=2*j*i;
                dfs(now+1);
                v[now].h=0;
                v[now].r=0;
                val-=j*j*i;
                sal-=2*j*i;
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        v[0].h=n/(m*m)+2;
        v[0].r=sqrt(n/m)+2;
        dfs(1);
        cout<<ans;
    }
    AC的最优化剪枝:
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    int nn,m,n,ans=0x7f7f7f7f;
    int ss[21],sv[21];
    void dfs(int t,int sal,int val,int lr,int lh){
        int maxh,i;
        if(t==0){
            if(val==n)    ans=min(ans,sal);
            return;
        }
        if(val+sv[t]>n) return;
        if(sal+ss[t]>ans) return; 
        if(sal+2*(n-val)/lr>ans) return;//第三重剪枝:假设剩余所有的体积都用来做下一层那么此时下一层的体积是最大,而半径会最大,从而表面积最小 
        for(int r=lr-1;r>=t;r--){ 
            if(t==m) sal=r*r;
            maxh=min((n-val-sv[t-1])/(r*r),lh-1);
            for(int h=maxh;h>=t;h--)
                  dfs(t-1,sal+2*r*h,val+r*r*h,r,h);
        }
    }
    int main(){
        //freopen("cake.in","r",stdin);
        //freopen("cake.out","w",stdout);
        int i;
        cin>>n>>m;
        for(i=1;i<=m;++i){ 
            ss[i]=2*i*i+ss[i-1];
            sv[i]=i*i*i+sv[i-1];
        }
        dfs(m,0,0,sqrt(n),n);
        if(ans==0x7f7f7f7f)    cout<<"0";
        else cout<<ans; 
        return 0;    
    }
     
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    TongJI Online Judge预赛(3): Game
    堆栈小应用:配对
    在.net中使用Udp协议创建简单的聊天程序
    TongJI Online Judge预赛(2): LOVE LETTER
    全排列问题之递归求解
    如何打造RSS阅读器
    Html 常用标志总结
    实现页面的分帧显示
    每天OnlineJudge之 “数素数”
    文本编辑器中,如何设计 撤销/重复栈
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7467266.html
Copyright © 2011-2022 走看看