• 「NOI1999」「LuoguP1731」生日蛋糕(爆搜剪枝


    题目背景

    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

    题解

    可以说是童年阴影了。

    众所周知的一道爆搜题,考点大概是剪枝?

     1 /*
     2     qwerta
     3     P1731 [NOI1999]生日蛋糕
     4     Accepted
     5     100
     6     代码 C++,1.45KB
     7     提交时间 2018-10-10 11:55:48
     8     耗时/内存
     9     760ms, 1256KB
    10 */
    11 #include<iostream>
    12 #include<cstdio>
    13 #include<cmath>
    14 using namespace std;
    15 #define R register
    16 int n,m;
    17 long long q=999999999999999;
    18 int f[16][103][10003];
    19 int fx[21][2];
    20 void search(int d,int rbef,int hbef,int vres,int sbef)//d:深度 rbef:上一层半径 hbef:上一层高度 vres:还剩的体积 sbef:已经用了多少面积
    21 {
    22     if(d==m+1)
    23     {
    24         if(vres==0)
    25           q=min(q,(long long)sbef);//搜到了就更新
    26           return;
    27     }
    28     if(vres<=0)return;//没体积了,剪掉
    29     if(sbef>q)return;//面积大了,剪掉
    30     if(rbef<=(m-d+1))return;//半径小了不够搭这么多层,剪掉
    31     if(hbef<=(m-d+1))return;//高度矮了不够搭这么多层,剪掉
    32     if(2*vres/rbef+sbef>q)return;//划重点!如果当前体积的最小面积还大了,剪掉
    33     //
    34     if(fx[d][0])//记忆化 fx[d][0]记录还剩d层时至少要的体积,fx[d][1]为面积
    35     {         
    36         if(fx[d][0]>vres)return;//剩体积的不够用,剪掉
    37         if(fx[d][1]+sbef>q)return;//最小的法子涂也面积大了,剪掉
    38     }
    39     else 
    40     {
    41         int v=0,s=0;
    42         for(R int i=d;i<=m;++i)//for一遍
    43         {
    44             int r=(m+1-i);
    45             int h=(m+1-i);
    46             v+=r*r*h,s+=2*r*h;
    47         }
    48         fx[d][0]=v;
    49         fx[d][1]=s;
    50         if(v>vres)return;
    51         if(s+sbef>q)return;
    52     }
    53     //
    54     if(f[d][rbef][hbef])//记录在d,rbef,hbef的情况下的最大体积
    55     {
    56         if(f[d][rbef][hbef]<vres)return;//往大了搭还小了,剪掉
    57     }
    58     else
    59     {
    60         int v=0;
    61         for(R int i=d;i<=m;++i)
    62         {
    63             int r=(rbef-(i-(d-1)));
    64             int h=(hbef-(i-(d-1)));
    65             v+=r*r*h;
    66         }
    67         f[d][rbef][hbef]=v;
    68         if(v<vres)return;
    69     }
    70     //剪爽了,开始搜
    71     for(R int r=1;r<rbef;++r)
    72     for(R int h=1;h<hbef;++h)
    73     {
    74         int s=0;
    75         if(d==1)s=r*r;
    76         search(d+1,r,h,vres-r*r*h,sbef+s+2*r*h);
    77     }
    78     return;
    79 }
    80 int main()
    81 {
    82     //freopen("a.in","r",stdin);
    83     scanf("%d%d",&n,&m);
    84     search(1,101,10001,n,0);
    85     cout<<q;
    86     return 0;
    87 }
    代码又慢又长哦,真的要看吗QAQ
  • 相关阅读:
    为服务部署 Jekins的使用
    spring cloud
    docker
    WebSocket
    idea
    maven
    SQL四种语言(DDL、 DML、 DCL、 TCL)
    十大经典排序
    AVL树的旋转图解和简单实现
    多个线程交替打印
  • 原文地址:https://www.cnblogs.com/qwerta/p/9769563.html
Copyright © 2020-2023  润新知