diff --git a/python/cap4/test.py b/python/cap4/test.py new file mode 100644 index 0000000..a794673 --- /dev/null +++ b/python/cap4/test.py @@ -0,0 +1,35 @@ +n = 8 + +def generateBoard(): + board = list() + for i in range(n): + row[queens[i]] = "Q" + board.append("".join(row)) + row[queens[i]] = "." + return board + +def backtrack(row: int): + if row == n: + board = generateBoard() + solutions.append(board) + else: + for i in range(n): + if i in columns or row - i in diagonal1 or row + i in diagonal2: + continue + queens[row] = i + columns.add(i) + diagonal1.add(row - i) + diagonal2.add(row + i) + backtrack(row + 1) + columns.remove(i) + diagonal1.remove(row - i) + diagonal2.remove(row + i) + +solutions = list() +queens = [-1] * n +columns = set() +diagonal1 = set() +diagonal2 = set() +row = ["."] * n +backtrack(0) +print(solutions) \ No newline at end of file diff --git a/python/cap4/work1.py b/python/cap4/work1.py new file mode 100644 index 0000000..0fa76ee --- /dev/null +++ b/python/cap4/work1.py @@ -0,0 +1,49 @@ +# work1. 01背包问题 +# 设 dp[i][w] 表示在背包容量为 w 时,前 i 个物品能够达到的最大总价值。 +# 状态转移方程: +# 对于第 i 个物品,存在两种情况: +# 如果第 i 个物品的重量大于当前背包容量 w,则无法放入背包,此时 dp[i][w] 等于 dp[i-1][w],即不放入该物品。 +# 如果第 i 个物品的重量小于等于当前背包容量 w,则考虑放入或不放入背包两种情况,取其中价值更大的情况。 +# 如果放入第 i 个物品,则总价值为 values[i] + dp[i-1][w-weights[i]]。 +# 如果不放入第 i 个物品,则总价值为 dp[i-1][w]。 +# 综合考虑以上两种情况,dp[i][w] 的值为这两种情况中的较大值。 +# 初始化: +# 当没有物品可选时,背包能够达到的最大总价值为0,即 dp[0][w] = 0,其中 w 取值为0到背包容量 capacity。 +# 填充数组: +# 使用两层循环填充 dp 数组,外层循环遍历物品,内层循环遍历背包容量,根据状态转移方程更新 dp[i][w] 的值。 +# 回溯: +# 根据 dp 数组中存储的最优解,找出放入的是哪些物品。 +# 返回结果: +def knapsack(weights: list[int], values: list[int], capacity: int) -> int: + n = len(weights) + # 创建一个二维数组来存储子问题的解 + dp = [[0] * (capacity + 1) for _ in range(n + 1)] + + # 填充dp数组 + for i in range(1, n + 1): + for w in range(1, capacity + 1): + # 如果当前物品的重量大于背包容量,则不能放入背包 + if weights[i - 1] > w: + dp[i][w] = dp[i - 1][w] + else: + # 考虑放入或不放入当前物品,选择其中价值更大的方案 + dp[i][w] = max(dp[i - 1][w], values[i - 1] + dp[i - 1][w - weights[i - 1]]) + + # 找出放入背包的物品 + selectedItems = [] + i, w = n, capacity + while i > 0 and w > 0: + if dp[i][w] != dp[i - 1][w]: + selectedItems.append(i - 1) + w -= weights[i - 1] + i -= 1 + + return dp[n][capacity], selectedItems + +# 测试 +weights = [10, 20, 30, 40, 50] +values = [50, 120, 150, 210, 240] +capacity = 50 +max_value, selected_items = knapsack(weights, values, capacity) +print("最大价值:", max_value) +print("选择的物品索引:", selected_items) \ No newline at end of file diff --git a/python/cap4/work12.py b/python/cap4/work12.py new file mode 100644 index 0000000..8c1f628 --- /dev/null +++ b/python/cap4/work12.py @@ -0,0 +1,27 @@ +# work12 +# 有一个由数字1,2,…,9组成的数字串,长度不超过200, +# 问如何将M(1≤M≤20)个加号插入这个数字串中,使得所形成的算法表达式的值最小。 + +def get_num(nums: list[int]) -> int: + result = 0 + for num in list: + result = result*10 + num + return result + +dp = [] + +def solve(nums: list, p: int, x: int) -> int: + if dp[p][x] != -1: + return dp[p][x] + + if x == 0: + dp[p][0] = get_num(nums[0,p]) + return dp[p][0] + + for i in range(x, p-1, -1): + dp[p][x] = min(dp[p][x], solve(i, x-1)+get_num(nums[i:p])) + + return dp[p][x] + +result = solve([7,9,8,4,6], 5, 20) +print(result) \ No newline at end of file diff --git a/python/cap4/work4.py b/python/cap4/work4.py new file mode 100644 index 0000000..e4dda27 --- /dev/null +++ b/python/cap4/work4.py @@ -0,0 +1,19 @@ +# work4 求最大字字段和(同例15的解法,此处为python版本写法) +# o(n)时间复杂度,o(1)空间。 +# 一路扫描,currMaxSum为当前位置为止的最大和,当到下一个位置时,判断当前数字num加上currMaxSum是否会导致比当前num还小, +# 如果当前数字num加上currMaxSum是否会导致比当前num还小,则说明最大的和不应从前面开始,而是*至少*应当从当前的数字开始 +# 下一步比较结果与当前的最大和哪个大,取更大的作为结果 +def findMaxSum(nums: list[int]) -> int: + result = nums[0] + currMaxSum = nums[0] + for i in range(1, len(nums)): + num = nums[i] + currMaxSum = max(currMaxSum+num, num) + result = max(result, currMaxSum) + + return result + +# test +nums = [-2, 11, -4, -9, 13, -5, 7, -3] +result = findMaxSum(nums) +print("最大子段和:", result) diff --git a/python/cap4/work5.py b/python/cap4/work5.py new file mode 100644 index 0000000..3b8fde2 --- /dev/null +++ b/python/cap4/work5.py @@ -0,0 +1,50 @@ +# work5 八皇后问题 +# 在8乘8的国际象棋棋盘上,放8个皇后,皇后可以吃掉与之同行同列以及同一对角线上的其他皇后。 +# 为让她们共存,找出所有放置方法。 + +n = 4 + +queens = [-1]*n +used_columns = set() +used_left_diagonal = set() +used_right_diagonal = set() + +def can_put_queen(row, col): + return (col not in used_columns) and (row-col not in used_right_diagonal) and (row+col not in used_left_diagonal) + +def put_queen(row, col): + queens.append((row, col)) + used_columns.add(col) + used_right_diagonal.add(row-col) + used_left_diagonal.add(row+col) + +def remove_queen(row, col): + queens.remove((row, col)) + used_columns.remove(col) + used_right_diagonal.remove(row-col) + used_left_diagonal.remove(row+col) + +result = list() + +def queen(row: int) -> list[list[str]]: + if row == n: + rowText = ["."] * n + board = list() + for i in range(n): + rowText[queens[i]] = "Q" + board.append("".join(rowText)) + rowText[queens[i]] = "." + result.append(board) + for col in range(n): + if not can_put_queen(row, col): + continue + queens[row] = col + put_queen(row, col) + queen(row+1) + remove_queen(row, col) + +queen(0) +for board in result: + for row in board: + print(row) + print("------------") \ No newline at end of file