Merge pull request #208 from KPatr1ck/back_track

backtrack applications in python
This commit is contained in:
wangzheng0822 2018-12-25 14:40:56 +08:00 committed by GitHub
commit bec216bef4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 193 additions and 0 deletions

View 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))

View 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)

View 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)

View 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)