一. 动态规划问题
1.1 斐波那契数列问题
1.递归解法
"""
斐波那契数列问题实现,队列如上 1 1 2 3 5 8 13........
"""
# 递归版
class Fib:
def __init__(self):
pass
def fib_n(self, p):
if p == 0:
return 1
elif p == 1:
return 1
else:
return self.fib_n(p-1) + self.fib_n(p-2)
if __name__ == '__main__':
obj = Fib()
t = obj.fib_n(5)
print(t)
2.备忘录解法
备忘录解法的就是记录之前计算过的值,保存起来,然后下一次直接拿来用
def Fib(n):
num_list = [0] * (n+1)
def fib(n, num_list):
if num_list[n] > 0:
return num_list[n]
if n <= 1:
num_list[n] = 1
else:
num_list[n] = fib(n-1, num_list) + fib(n-2, num_list)
return num_list[n]
return fib(n, num_list)
print(Fib(5))
1.2 钢管切割问题
钢管切割动态规划问题的核心是 n长的钢管,先分成i米以及n-i两部分 p[i],即有 r[n] = max(p[i] + r[n-i]),依次遍历求最大值, 那么最大收益s为,
s = max(s, p[i] + func(p, n-i)), 其中当n为0时, r[0] = 0
def max_value(p, n, r):
for i in range(1, n + 1):
if n == 0:
return 0
if n <= 10:
q = 0
for j in range(1, i + 1):
q = max(q, p[j-1] + r[i - j])
r[i] = q
else:
q = 0
for j in range(1, i + 1):
q = max(q, p[(j - 1) % 10] + r[i - j])
r[i] = q
print(r)
return r[n]
def main():
p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30]
n = 8
r_obj = {}
for i in range(n):
r_obj[i] = 0
r_obj[1] = 1
t = max_value(p, n, r_obj)
print("最大收益为:", t)
if __name__ == '__main__':
main()
1.3 矩阵中字母搜索问题
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
给定 word = “ABCCED”, 返回 true.
给定 word = “SEE”, 返回 true.
给定 word = “ABCB”, 返回 false.
s = [
['A', 'B', 'C', 'E'],
['S', 'F', 'C', 'S'],
['A', 'D', 'E', 'E']
]
t = [
[False, False, False, False],
[False, False, False, False],
[False, False, False, False]
]
word = 'ABCCED'
class Solution:
def __init__(self):
self.pos = list() #
self.n = self.m = 0 # 用来储存行和列的数目
self.flag = False # 用来标志最终结果
self.l = 0 # 单词长度
self.target = "" # 目标要构建的单词
self.direction = [[1, 0], [-1, 0], [0, 1], [0, -1]] # 可以选的方向
def search(self, board, x, y, s):
if s == self.target:
self.flag = True
return # 如果构建中的字符串达到目标要构建的单词
if len(s) >= self.l:
return # 如果构建的字符的长度大了,就返回,防止无限增加
self.pos[x][y] = True # 把当前位置标记为已搜索,防止再次搜索。
for d in self.direction: # 遍历所有方向,上下左右
if 0 <= x + d[0] <= self.n - 1 and 0 <= y + d[1] <= self.m - 1 and not self.pos[x + d[0]][y + d[1]] and \
board[x + d[0]][y + d[1]] == self.target[len(s)]: # 只有当下个节点没有超过边界并且没有被访问过并且是下一个必须的组成单词的下一个字母时,我们才调用递归
self.search(board, x + d[0], y + d[1], s + board[x + d[0]][y + d[1]]) # 构建中的单词需要加上下一个字母,同时更新位置
if self.flag:
return # 如果找到了该单词,直接返回
self.pos[x][y] = False # 把当前标为未访问
def exist(self, board, word):
self.n = len(board) # 储存行数
if self.n == 0:
return False
self.m = len(board[0]) # 储存列数
if self.m == 0:
return False
self.l = len(word) # 储存单词长度
if self.l == 0 or self.l > self.n * self.m:
return False # 如果当前单词比所有字母连一起还长
self.target = word # 储存目标单词
self.pos = [[False for col in range(self.m)] for row in range(self.n)] # 构建一个检测有没有被访问的表
for i in range(self.n):
for j in range(self.m):
if board[i][j] == word[0]: # 如果当前字母等于第一个字母,开始递归
self.search(board, i, j, board[i][j])
return self.flag # 返回最终结果
if __name__ == '__main__':
s = [
['A', 'B', 'C', 'E'],
['S', 'F', 'C', 'S'],
['A', 'D', 'E', 'E']
]
word = 'ABCCEE'
s_obj = Solution()
k = s_obj.exist(s, word)
print(k)