zoukankan      html  css  js  c++  java
  • 深度优先搜索-生日蛋糕

    生日蛋糕 (百练1190)
    要制作一个体积为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 <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),
    表示蛋糕的层数为M。
    输出:仅一行,是一个正整数S(若无解则S = 0)。

    输入:
    100
    2
    输出:
    68

    思路:
    蛋糕的体积:V=Nπ=πR21H1+πR22H2+...+πR2nHn
    则:N=R21H1+R22H2+...+R2nHn
    其中(R1>R2>R3>...>Rn

    蛋糕的表面积:Q=Sπ=πR21+2πR1H1+2πR2H2+...+2πRnHn
    则:S=R21+2R1H1+2R2H2+...+2RnHn
    其中(R1>R2>R3>...>Rn且H1>H2>H3>...>Hn)

    当N取最大值10000时,最大半径是当h=1时,即r=100。同理,最大的h=10000

    深度优先搜索,枚举什么?
    枚举每一层可能的高度和半径。
    如何确定搜索范围?
    底层蛋糕的最大可能半径和最大可能高度
    搜索顺序,哪些地方体现搜索顺序?
    从底层往上搭蛋糕,而不是从顶层往下搭

    剪枝1:搭建过程中发现已建好的面积已经超过目前求得的最优表面
    积,或者预见到搭完后面积一定会超过目前最优表面积,则停止搭建(最优性剪枝)
    剪枝2:搭建过程中预见到再往上搭,高度已经无法安排,或者半径
    已经无法安排,则停止搭建(可行性剪枝)
    剪枝3:搭建过程中发现还没搭的那些层的体积,一定会超过还缺的
    体积,则停止搭建(可行性剪枝)
    剪枝4:搭建过程中发现还没搭的那些层的体积,最大也到不了还缺
    的体积,则停止搭建(可行性剪枝)

    假设构建2层蛋糕,最低层为r1,h1,第二层为r2,h2,公式如下:
    V=Nπ=πr1平方h1 + πr2平方h2,N=r1平方h1 + r2平方h2
    同理:蛋糕表面积=蛋糕最底层蛋糕的圆面积 + 每层蛋糕的侧面积
    因为每层蛋糕的顶面积刚好就是最底层蛋糕的圆面积
    Q=Sπ= πr1平方 + 2πr1h1 + 2πr2h2,提取π公因子
    S = r1平方 + 2r1h1 + 2r2h2

    python 代码实现:
     1 import math
     2 
     3 # N-蛋糕的总体积,M-层数
     4 N, M = 0, 0
     5 # 最优表面积,初值为无穷大
     6 minArea = float("inf")
     7 # 正在搭建中的蛋糕的表面积
     8 area = 0
     9 # 统计循环的次数
    10 num = 0
    11 # 当前体积
    12 currentVolume = 0
    13 
    14 # 要用m层去凑体积v,最底层半径不能超过r,高度不能超过h
    15 # 求出最小表面积放入minArea
    16 def Dfs(v, m, r, h):
    17     global N, M, minArea, area, num, currentVolume
    18     # m=0,v=0时,说明蛋糕搭建成功,因为的递减,m=0说明不需要搭层数了
    19     # 而且v=0,说明体积大小也搭建符合题目的要求了,v!=0,说明已经搭到
    20     # 顶层蛋糕了,但是体积没有搭到输入N的要求,所以失败了
    21     if m == 0:
    22         if v == 0:
    23             # 找到一个最优值与之前的最优值进行比较,如果更小则替换
    24             minArea = min(minArea, area)
    25             return
    26         else:
    27             return
    28     # 做m层蛋糕,但是体积v是0或者小于0是做不到的
    29     if v <= 0:
    30         return
    31     # 半径i从最大半径r开始依次递减1,直到m,因为如果要做m层蛋糕,
    32     # 最底层的蛋糕的半径最小值为m,同理最底层蛋糕的高度最小值也为m
    33     # 因为题目要求是整数,而且逐层半径、高度最小相差1
    34     for i in range(r, m-1, -1):
    35         # S = r1平方+各层蛋糕的侧面积
    36         # 蛋糕的底面积
    37         if m == M:
    38             area = i * i
    39         for j in range(h, m-1, -1):
    40             # currentVolume表示搭好的当前蛋糕的体积
    41             currentVolume = currentVolume + (i*i*j)
    42             # 剪枝:如果按此半径和高度,搭好的蛋糕的体积超过输入的N,则该方案不可行
    43             if currentVolume > N:
    44                 # 深度遍历需要回溯,之前加过这个值了,但是该条路径走不通,因此要把之前加的值减回去
    45                 currentVolume -= (i * i * j)
    46                 continue
    47             area += 2 * i * j
    48             # 剪枝:如果计算出正在搭建的表面积已经大于曾经计算出的最优表面积
    49             # 则不需要再往下搭建了,即使能搭建出来也不是最优的表面积
    50             if area > minArea:
    51                 # 该条路径走不通,因此要把之前加的值减回去
    52                 area -= 2 * i * j
    53                 continue
    54             num += 1
    55             Dfs(v-i*i*j, m-1, i-1, j-1)
    56             # 走过的路重新往回走,需要把原来增加的值减回去,以保证下次新的走法走到该点时,
    57             # area、currentVolume的值是与原初始化的值
    58             area -= 2 * i * j
    59             currentVolume -= (i * i * j)
    60 
    61 
    62 def main():
    63     global N, M, minArea, num
    64     N, M = map(int, input().split())
    65     # 这里对半径和高度都是做个初略的假设
    66     # 最大半径是假设蛋糕就1层,高度是1的情况,根据公式,可以对N开根号即可得最大值
    67     # 最大高度是假设蛋糕的半径是1的情况,N就是高度的最大值
    68     Dfs(N, M, int(math.sqrt(N)), N)
    69     if minArea == float("inf"):
    70         print("%d" % 0)
    71     else:
    72         print("S = %d,循环次数:%d" % (minArea, num))
    73 
    74 
    75 if __name__ == '__main__':
    76     main()


  • 相关阅读:
    Representation Data in OpenCascade BRep
    Render OpenCascade Geometry Surfaces in OpenSceneGraph
    Render OpenCascade Geometry Curves in OpenSceneGraph
    OpenCascade Shape Representation in OpenSceneGraph
    Geometry Surface of OpenCascade BRep
    Geometry Curve of OpenCascade BRep
    Tyvj2017清北冬令营入学测试
    Spfa算法模板
    洛谷1016 旅行家的预算
    洛谷1290 欧几里得的游戏
  • 原文地址:https://www.cnblogs.com/an-wl/p/13282675.html
Copyright © 2011-2022 走看看