• [NOI1999]生日蛋糕题解


    还是被这个立体的结构吓到了,隔了半年才A.

    题目链接:!...!

    题目描述

    7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层

    生日蛋糕,每层都是一个圆柱体。

    设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i<M时,要求R_i>R_{i+1}Ri>Ri+1H_i>H_{i+1}Hi>Hi+1

    由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。

    令Q= Sπ

    请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。

    (除Q外,以上所有数据皆为正整数)

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入样例:

    100

    输出样例:

    68

    解题思路:

    1.搜索要搜什么?

    (1)符合体积要求的最小表面积

    2.搜索记录什么?

    (1)已使用体积

    (2)已使用面积

    (3)第几层

    (4)上一层半径

    (5)上一层高度

    3.如何剪枝?

    可行性剪枝:

    (1)当前体积+预算最小体积>N

    最优性剪枝:

    (1)当前表面积+预算最小侧面积>ans

    (2)(2*(n-v)/r)+s>ans根据体积公式和面积公式求。

    解释:如果当前表面积+预算最小侧面积(取极限)>ans

    上下界剪枝:

    (1)r和h的范围可以确定的,这里我就不记录了,可以根据体积公式求得。

    优化搜索顺序:

    (1)从大到小循环,减少搜索状态。

    代码:

    #include<bits/stdc++.h>
    #define ll long long 
    #define R register
    using namespace std;
    const int N=20;
    int n,m,minh[N],minr[N],sums[N],sumv[N],ans=0x3f3f3f3f;
    inline int read(){
        int s=0,w=1; 
        char ch=getchar(); 
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return s*w; 
    }
    inline void dfs(R int dep,R int lstr,R int lsth,R int s,R int v){
        if(dep==0){
            if(v==n)
            ans=min(ans,s);
            return;
        }
        if(v+sumv[dep]>n)return;
        if(s+sums[dep]>=ans)return;
        if((2*(n-v)/lstr)+s>ans)return;
        for(R int i=min(lstr-1,(int)sqrt(n-v));i>=minr[dep];i--)
        for(R int j=min(lsth-1,(n-v)/(i*i));j>=minh[dep];j--)
        dfs(dep-1,i,j,s+2*i*j,v+i*i*j);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(R int i=1;i<=m;i++){
        minh[i]=i;minr[i]=i;
        sums[i]=sums[i-1]+2*minr[i]*minh[i];
        sumv[i]=sumv[i-1]+minr[i]*minr[i]*minh[i];
        }
        for(R int i=(int)sqrt(n);i>=minr[m];i--)
        for(R int j=n/(i*i);j>=minh[m];j--)
        dfs(m-1,i,j,i*i+2*i*j,i*i*j);
        if(ans==0x3f3f3f3f)
        printf("0");
        else printf("%d",ans);
        return 0;
        
    }
  • 相关阅读:
    Lambda Expression in C#
    DirectorySearcher LDAP
    摘录 LDAP
    The return types for the following stored procedures could not be detected
    无法调试存储过程,无法启动T-SQL调试
    根据窗口句柄显示窗体
    还原数据库时提示空间不足
    xml格式发送
    ../ 上一级目录
    匿名函数 invoke
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9851832.html
Copyright © 2020-2023  润新知