diff --git a/python/39_back_track/01_bag.py b/python/39_back_track/01_bag.py new file mode 100644 index 0000000..53c7731 --- /dev/null +++ b/python/39_back_track/01_bag.py @@ -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)) diff --git a/python/39_back_track/eight_queens.py b/python/39_back_track/eight_queens.py new file mode 100644 index 0000000..a25b728 --- /dev/null +++ b/python/39_back_track/eight_queens.py @@ -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) diff --git a/python/39_back_track/permutations.py b/python/39_back_track/permutations.py new file mode 100644 index 0000000..b02a876 --- /dev/null +++ b/python/39_back_track/permutations.py @@ -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) + diff --git a/python/39_back_track/regex.py b/python/39_back_track/regex.py new file mode 100644 index 0000000..001cac7 --- /dev/null +++ b/python/39_back_track/regex.py @@ -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)