Skip to content

Commit

Permalink
Merge pull request wangzheng0822#208 from KPatr1ck/back_track
Browse files Browse the repository at this point in the history
backtrack applications in python
  • Loading branch information
wangzheng0822 authored Dec 25, 2018
2 parents 65918ed + ec99c67 commit bec216b
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 0 deletions.
59 changes: 59 additions & 0 deletions python/39_back_track/01_bag.py
Original file line number Diff line number Diff line change
@@ -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 changes: 57 additions & 0 deletions python/39_back_track/eight_queens.py
Original file line number Diff line number Diff line change
@@ -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 changes: 42 additions & 0 deletions python/39_back_track/permutations.py
Original file line number Diff line number Diff line change
@@ -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 changes: 35 additions & 0 deletions python/39_back_track/regex.py
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit bec216b

Please sign in to comment.