zoukankan      html  css  js  c++  java
  • 动态规划-分蛋糕V2

    分蛋糕:
    有一块矩形大蛋糕,长和宽分别是整数w?、h。现要将其切成m块小蛋糕,
    每个小蛋糕都必须是矩形、且长和宽均为整数。切蛋糕时,每次切一块蛋糕,
    将其分成两个矩形蛋糕。请计算:最后得到的m块小蛋糕中,最大的那块蛋糕的面积下限。
    假设w= 4,?h= 4,?m= 4,则下面的切法可使得其中最大蛋糕块的面积最小。
    假设w= 4,?h= 4,?m= 3,则下面的切法会使得其中最大蛋糕块的面积最小:
    Input
    共有多行,每行表示一个测试案例。每行是三个用空格分开的整数w, h, m ,
    其中1 ≤ w, h, m ≤ 20 , m ≤ wh. 当 w = h = m = 0 时不需要处理,
    表示输入结束。
    Output
    每个测试案例的结果占一行,输出一个整数,表示最大蛋糕块的面积下限。
    Sample Input
    4 4 4
    4 4 3
    0 0 0
    Sample Output
    4
    6

    """
    # 4 4 3
    """
    [
    [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1], [-1, -1, -1], [-1, -1, -1]],
    [[-1, -1, -1], [1, inf, inf], [2, 1, inf], [3, 2, 1], [4, 2, 2]],
    [[-1, -1, -1], [2, 1, inf], [4, 2, 2], [6, 3, 2], [8, 4, 3]],
    [[-1, -1, -1], [3, 2, 1], [6, 3, 2], [9, 6, 3], [12, 6, 4]],
    [[-1, -1, -1], [4, 2, 2], [8, 4, 3], [12, 6, 4], [16, 8, 【6】]]
    ]
    【6】位置,表示w=4,h=4,d=2的值
    思路:递推就是就是后续的值是由前面计算过的值求出来的。
    只要理解其中的一种情况,如:minBiggestArea[4][4][2]
    求w=4,h=4,d=2的最大蛋糕的最小值
    对蛋糕切1刀下去后,假设第1刀竖切,位置在w=3的位置,
    那么就分成了2块蛋糕,那么用剩下的刀数分别求这两块蛋糕的最大蛋糕的最小值
    假设左边最大蛋糕的最小值v1,右边最大蛋糕的最小值v2,
    max(v1,v2),两者中的最大值,既是minBiggestArea[4][4][2]第一刀切在w=3位置
    最大蛋糕的最小值。
    总共可以切2刀,第1刀已经切了,那么左右蛋糕最多只能切1刀
    其中一种情况:遍历左边切0刀,右边只能切1刀
    v1=minBiggestArea[3][4][0],v2=minBiggestArea[1][4][1]
    其中一种情况:遍历左边切1刀,右边只能切0刀
    v1=minBiggestArea[3][4][1],v2=minBiggestArea[1][4][0]
    minBiggestArea[4][4][2] = max(v1,v2)
    因为不同的切法,max(v1,v2)能求出许多不同的值,题目要求最小的值,因此
    需要从那么多个值当中找出最小的值存到minBiggestArea[4][4][2]

    python代码:
    # minBigestArea三维列表,0:宽,1:高,2:共切几刀,在w,h的长方形切m刀最大蛋糕的面积最小值
    minBiggestArea = []
    INF = float("inf")
    
    
    # w-宽度 h-高度 d-刀数
    def BiggestCakeMinSize(w, h, d):
        global minBiggestArea
        # 宽度
        for i in range(1, w+1):
            # 高度
            for j in range(1, h+1):
                # 枚举共可以切的刀数
                for k in range(1, d+1):
                    if k+1 > i*j:
                        minBiggestArea[i][j][k] = INF
                    else:
                        # 竖切
                        SV = INF
                        sv, sh = 0, 0
                        # 枚举竖着切宽度的位置
                        for ii in range(1, i):
                            for kk in range(0, k):
                                sv = max(minBiggestArea[ii][j][kk], minBiggestArea[i-ii][j][k-1-kk])
                                SV = min(SV, sv)
                        # 横切
                        SH = INF
                        # 枚举横着切高度的位置
                        for jj in range(1, j):
                            for kk in range(0, k):
                                sh = max(minBiggestArea[i][jj][kk], minBiggestArea[i][j-jj][k-1-kk])
                                SH = min(SH, sh)
                        minBiggestArea[i][j][k] = min(SV, SH)
        return minBiggestArea[w][h][d]
    
    
    def main():
        global minBiggestArea
        while True:
            w, h, m = map(int, input().split())
            if w == 0 and h == 0 and m == 0:
                break
            # 构建1个三维列表,因为列表的序号从0开始计算,为了计算方便w、h多增加1,
            # 列表中w、h位置0的值没有意义,不存储数据,仅为计算方便
            # 三维列表从1开始存储,初始化为-1,如果计算过,就存储值下来,避免重复计算,提高效率
            # m这个位置存储的是刀数,要分成m块,需要m-1刀,比如m=3,只需要2刀,所以只需要生成0、1、2
            # 因此m的位置不需要增加1
            minBiggestArea = [[[-1 for i in range(m)] for i in range(h+1)] for i in range(w+1)]
            # 先计算如果一刀都不切的情况下的值,最大蛋糕最小值即宽*高
            for i in range(1, w+1):
                for j in range(1, h+1):
                    minBiggestArea[i][j][0] = i*j
            """
            [
                [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1], [-1, -1, -1], [-1, -1, -1]],
                [[-1, -1, -1], [1, -1, -1], [2, -1, -1], [3, -1, -1], [4, -1, -1]],
                [[-1, -1, -1], [2, -1, -1], [4, -1, -1], [6, -1, -1], [8, -1, -1]],
                [[-1, -1, -1], [3, -1, -1], [6, -1, -1], [9, -1, -1], [12, -1, -1]],
                [[-1, -1, -1], [4, -1, -1], [8, -1, -1], [12, -1, -1], [16, -1, -1]]
            ]
            """
            # m块蛋糕需要切m-1刀
            optimalValue = BiggestCakeMinSize(w, h, m-1)
            print("最大蛋糕块的面积下限为:%d" % optimalValue)
    
        return 0
    
    
    if __name__ == '__main__':
        main()
  • 相关阅读:
    Vue生命周期,及父子组件生命周期顺序
    使用jquery制作可视化的组织结构
    用Moon.Orm来做分页数据显示
    bash脚本之代码统计
    CSS选择符总结
    css选择符归类
    APP测试与WEB测试的区别
    使用Jmeter 对APP进行压力测试
    Python基础之数据类型
    App测试要点以及Bug分类
  • 原文地址:https://www.cnblogs.com/an-wl/p/13198070.html
Copyright © 2011-2022 走看看