Merge pull request #208 from KPatr1ck/back_track
backtrack applications in python
This commit is contained in:
commit
bec216bef4
59
python/39_back_track/01_bag.py
Normal file
59
python/39_back_track/01_bag.py
Normal file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
from typing import List
|
||||
|
||||
# 背包选取的物品列表
|
||||
picks = []
|
||||
picks_with_max_value = []
|
||||
|
||||
|
||||
def bag(capacity: int, cur_weight: int, items_info: List, pick_idx: int):
|
||||
"""
|
||||
回溯法解01背包,穷举
|
||||
:param capacity: 背包容量
|
||||
:param cur_weight: 背包当前重量
|
||||
:param items_info: 物品的重量和价值信息
|
||||
:param pick_idx: 当前物品的索引
|
||||
:return:
|
||||
"""
|
||||
# 考察完所有物品,或者在中途已经装满
|
||||
if pick_idx >= len(items_info) or cur_weight == capacity:
|
||||
global picks_with_max_value
|
||||
if get_value(items_info, picks) > \
|
||||
get_value(items_info, picks_with_max_value):
|
||||
picks_with_max_value = picks.copy()
|
||||
else:
|
||||
item_weight = items_info[pick_idx][0]
|
||||
if cur_weight + item_weight <= capacity: # 选
|
||||
picks[pick_idx] = 1
|
||||
bag(capacity, cur_weight + item_weight, items_info, pick_idx + 1)
|
||||
|
||||
picks[pick_idx] = 0 # 不选
|
||||
bag(capacity, cur_weight, items_info, pick_idx + 1)
|
||||
|
||||
|
||||
def get_value(items_info: List, pick_items: List):
|
||||
values = [_[1] for _ in items_info]
|
||||
return sum([a*b for a, b in zip(values, pick_items)])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# [(weight, value), ...]
|
||||
items_info = [(3, 5), (2, 2), (1, 4), (1, 2), (4, 10)]
|
||||
capacity = 8
|
||||
|
||||
print('--- items info ---')
|
||||
print(items_info)
|
||||
|
||||
print('\n--- capacity ---')
|
||||
print(capacity)
|
||||
|
||||
picks = [0] * len(items_info)
|
||||
bag(capacity, 0, items_info, 0)
|
||||
|
||||
print('\n--- picks ---')
|
||||
print(picks_with_max_value)
|
||||
|
||||
print('\n--- value ---')
|
||||
print(get_value(items_info, picks_with_max_value))
|
57
python/39_back_track/eight_queens.py
Normal file
57
python/39_back_track/eight_queens.py
Normal file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# 棋盘尺寸
|
||||
BOARD_SIZE = 8
|
||||
|
||||
solution_count = 0
|
||||
queen_list = [0] * BOARD_SIZE
|
||||
|
||||
|
||||
def eight_queens(cur_column: int):
|
||||
"""
|
||||
输出所有符合要求的八皇后序列
|
||||
用一个长度为8的数组代表棋盘的列,数组的数字则为当前列上皇后所在的行数
|
||||
:return:
|
||||
"""
|
||||
if cur_column >= BOARD_SIZE:
|
||||
global solution_count
|
||||
solution_count += 1
|
||||
# 解
|
||||
print(queen_list)
|
||||
else:
|
||||
for i in range(BOARD_SIZE):
|
||||
if is_valid_pos(cur_column, i):
|
||||
queen_list[cur_column] = i
|
||||
eight_queens(cur_column + 1)
|
||||
|
||||
|
||||
def is_valid_pos(cur_column: int, pos: int) -> bool:
|
||||
"""
|
||||
因为采取的是每列放置1个皇后的做法
|
||||
所以检查的时候不必检查列的合法性,只需要检查行和对角
|
||||
1. 行:检查数组在下标为cur_column之前的元素是否已存在pos
|
||||
2. 对角:检查数组在下标为cur_column之前的元素,其行的间距pos - QUEEN_LIST[i]
|
||||
和列的间距cur_column - i是否一致
|
||||
:param cur_column:
|
||||
:param pos:
|
||||
:return:
|
||||
"""
|
||||
i = 0
|
||||
while i < cur_column:
|
||||
# 同行
|
||||
if queen_list[i] == pos:
|
||||
return False
|
||||
# 对角线
|
||||
if cur_column - i == abs(pos - queen_list[i]):
|
||||
return False
|
||||
i += 1
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('--- eight queens sequence ---')
|
||||
eight_queens(0)
|
||||
|
||||
print('\n--- solution count ---')
|
||||
print(solution_count)
|
42
python/39_back_track/permutations.py
Normal file
42
python/39_back_track/permutations.py
Normal file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
from typing import List
|
||||
|
||||
permutations_list = [] # 全局变量,用于记录每个输出
|
||||
|
||||
|
||||
def permutations(nums: List, n: int, pick_count: int):
|
||||
"""
|
||||
从nums选取n个数的全排列
|
||||
|
||||
回溯法,用一个栈记录当前路径信息
|
||||
当满足n==0时,说明栈中的数已足够,输出并终止遍历
|
||||
:param nums:
|
||||
:param n:
|
||||
:param pick_count:
|
||||
:return:
|
||||
"""
|
||||
if n == 0:
|
||||
print(permutations_list)
|
||||
else:
|
||||
for i in range(len(nums) - pick_count):
|
||||
permutations_list[pick_count] = nums[i]
|
||||
nums[i], nums[len(nums) - pick_count - 1] = nums[len(nums) - pick_count - 1], nums[i]
|
||||
permutations(nums, n-1, pick_count+1)
|
||||
nums[i], nums[len(nums) - pick_count - 1] = nums[len(nums) - pick_count - 1], nums[i]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
nums = [1, 2, 3, 4]
|
||||
n = 3
|
||||
print('--- list ---')
|
||||
print(nums)
|
||||
|
||||
print('\n--- pick num ---')
|
||||
print(n)
|
||||
|
||||
print('\n--- permutation list ---')
|
||||
permutations_list = [0] * n
|
||||
permutations(nums, n, 0)
|
||||
|
35
python/39_back_track/regex.py
Normal file
35
python/39_back_track/regex.py
Normal file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
is_match = False
|
||||
|
||||
|
||||
def rmatch(r_idx: int, m_idx: int, regex: str, main: str):
|
||||
global is_match
|
||||
if is_match:
|
||||
return
|
||||
|
||||
if r_idx >= len(regex): # 正则串全部匹配好了
|
||||
is_match = True
|
||||
return
|
||||
|
||||
if m_idx >= len(main) and r_idx < len(regex): # 正则串没匹配完,但是主串已经没得匹配了
|
||||
is_match = False
|
||||
return
|
||||
|
||||
if regex[r_idx] == '*': # * 匹配1个或多个任意字符,递归搜索每一种情况
|
||||
for i in range(m_idx, len(main)):
|
||||
rmatch(r_idx+1, i+1, regex, main)
|
||||
elif regex[r_idx] == '?': # ? 匹配0个或1个任意字符,两种情况
|
||||
rmatch(r_idx+1, m_idx+1, regex, main)
|
||||
rmatch(r_idx+1, m_idx, regex, main)
|
||||
else: # 非特殊字符需要精确匹配
|
||||
if regex[r_idx] == main[m_idx]:
|
||||
rmatch(r_idx+1, m_idx+1, regex, main)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
regex = 'ab*eee?d'
|
||||
main = 'abcdsadfkjlekjoiwjiojieeecd'
|
||||
rmatch(0, 0, regex, main)
|
||||
print(is_match)
|
Loading…
Reference in New Issue
Block a user