惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 【当耐特】
N
Netflix TechBlog - Medium
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
MongoDB | Blog
MongoDB | Blog
有赞技术团队
有赞技术团队
Engineering at Meta
Engineering at Meta
M
MIT News - Artificial intelligence
Google DeepMind News
Google DeepMind News
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
T
Tailwind CSS Blog
小众软件
小众软件
J
Java Code Geeks
人人都是产品经理
人人都是产品经理
博客园_首页
MyScale Blog
MyScale Blog
博客园 - 聂微东
V
Visual Studio Blog
The Cloudflare Blog
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42

博客园 - StudyNLP

python把中文汉字转拼音,存储到excel表格 算法结束篇 贪心-钓鱼问题 贪心-放置雷达 贪心-Stall Reservations 贪心-电影节 贪心-圣诞老人的礼物 广度优先搜索-八数码问题 广度优先搜索-鸣人和佐助 广度优先搜索-迷宫问题 广度优先搜索-抓住那头牛 深度优先搜索-生日蛋糕 深度优先搜索-Roads 深度优先搜索-踩方格 深度优先搜索-城堡问题 动态规划-分蛋糕V2 动态规划-滑雪 动态规划-0-1背包问题 动态规划-神奇的口袋V2
动态规划-分蛋糕V1
StudyNLP · 2020-06-24 · via 博客园 - StudyNLP
 1 # 4 4 3
 2 # [
 3 # [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1], [-1, -1, -1], [-1, -1, -1]],
 4 # [[-1, -1, -1], [1, -1, -1], [2, -1, -1], [3, -1, -1], [4, 2, -1]],
 5 # [[-1, -1, -1], [2, -1, -1], [4, -1, -1], [6, -1, -1], [8, 4, -1]],
 6 # [[-1, -1, -1], [3, -1, -1], [6, -1, -1], [9, -1, -1], [12, 6, -1]],
 7 # [[-1, -1, -1], [4, 2, -1], [8, 4, -1], [12, 6, -1], [-1, -1, 6]]
 8 # ]
 9 # DFS(4,4,2) = max(DFS(3,4,1),DFS(1,4,0))
10 # 6 =  max(6,4)
11 
12 # minBigestArea三维列表,0:宽,1:高,2:共切几刀,在w,h的长方形切m刀最大蛋糕的面积最小值
13 minBiggestArea = []
14 INF = float("inf")
15 
16 
17 # 竖着切
18 def SV(w, h, k):
19     sv = INF
20     # 第一刀竖着切,因为是整数,刀的位置在1——w之间,遍历第一刀切的位置
21     for i in range(1, w):
22         # 第一刀切下去了,那么就会产生左右两块蛋糕,剩下切的刀数就是0——k-1,所以遍历循环的范围是k
23         # 第一刀切下去后,产生2块蛋糕,那么对左边的蛋糕可能切几刀,取值从0——k-1
24         # 知道左边切下去的刀数了,那么就可以计算出还剩余的刀数就给右边来切
25         # 以4 4 3为例,如果第一刀切的位置为3,那么就会产生2块蛋糕,左边w=3,h=4 ,右边w=1,h=4
26         # 竖切的情况:
27         # DFS(4,4,2) = max(DFS(3,4,0),DFS(1,4,1))或者max(DFS(3,4,1),DFS(1,4,0))
28         # 因为我们需要找最大那块蛋糕的值,因此要取左右2块蛋糕的max值
29         # 那么不同的切法,最大那块蛋糕的值有许多种,题目要求最小的,所以最后就有个min
30         for kk in range(0, k):
31             # 求1切下去后左边蛋糕在i,h,kk的情况下最大蛋糕的最小值
32             leftValue = DFS(i, h, kk)
33             # 求1切下去后右边边蛋糕在w-i,h,k-1-kk的情况下最大蛋糕的最小值
34             rightValue = DFS(w-i, h, k-1-kk)
35             # 左右蛋糕最大蛋糕的最小值求出了,合起来比较,那么sv在w、h、k下最大蛋糕的最小值即可算出
36             sv = min(sv, max(leftValue, rightValue))
37     return sv
38 
39 
40 # 横着切与竖的原理是一样的,唯一区别这里是w不变,h变了
41 def SH(w, h, k):
42     sh = INF
43     for i in range(1, h):
44         for kk in range(0, k):
45             leftValue = DFS(w, i, kk)
46             rightValue = DFS(w, h-i, k-1-kk)
47             sh = min(sh, max(leftValue, rightValue))
48     return sh
49 
50 
51 # w-宽度 h-高度 k-共切几刀
52 def DFS(w, h, k):
53     global minBiggestArea
54     # 如果该位置的最大蛋糕最小值已经计算好了,不需要重复计算,直接读出
55     if minBiggestArea[w][h][k] != -1:
56         return minBiggestArea[w][h][k]
57     # w=4,h=4,因为要求蛋糕的边是整数,因此最多可以产生16块小蛋糕,也就是最多可以切15刀
58     # 如果切16刀,蛋糕分不出17块,完成不了,因此返回无穷大
59     if w * h < k + 1:
60         minBiggestArea[w][h][k] = INF
61         return minBiggestArea[w][h][k]
62     # 如果一刀都不切,那么w*h就是最大蛋糕的最小值
63     if k == 0:
64         minBiggestArea[w][h][k] = w * h
65         return minBiggestArea[w][h][k]
66     # 因为蛋糕第一刀切下去,有竖、横两个方向,所以要分别求
67     # 第一刀竖着切最大蛋糕的最小值,横着切所得最大蛋糕的最小值
68     # 然后再对这2个取最小值,即得该大小蛋糕,共切几刀的最大蛋糕最小值
69     minBiggestArea[w][h][k] = min(SV(w, h, k), SH(w, h, k))
70     return minBiggestArea[w][h][k]
71 
72 
73 def main():
74     global minBiggestArea
75     while True:
76         w, h, m = map(int, input().split())
77         if w == 0 and h == 0 and m == 0:
78             break
79         # 构建1个三维列表,因为列表的序号从0开始计算,为了计算方便w、h多增加1,
80         # 列表中w、h位置0的值没有意义,不存储数据,仅为计算方便
81         # 三维列表从1开始存储,初始化为-1,如果计算过,就存储值下来,避免重复计算,提高效率
82         # m这个位置存储的是刀数,要分成m块,需要m-1刀,比如m=3,只需要2刀,所以只需要生成0、1、2
83         # 因此m的位置不需要增加1
84         minBiggestArea = [[[-1 for i in range(m)] for i in range(h+1)] for i in range(w+1)]
85         # print(minBigestArea)
86         # w-宽度、h-高度,函数的第3个参数表示总共刀数,切m-1刀,即可得到m块蛋糕
87         optimalValue = DFS(w, h, m-1)
88         print("最大蛋糕块的面积下限为:%d" % optimalValue)
89 
90     return 0
91 
92 
93 if __name__ == '__main__':
94     main()