采用蛮力法、回溯法、动态规划实现01背包问题,并对比起时间复杂度进行分析
时间: 2025-07-06 13:53:29 浏览: 6
### 使用蛮力法、回溯法和动态规划实现01背包问题
#### 蛮力法解决01背包问题
蛮力法通过枚举所有可能的选择组合来解决问题。对于有 \( n \) 个物品的情况,共有 \( 2^n \) 种不同的选择方式。
```python
def knapsack_brute_force(weights, values, capacity):
best_value = 0
def helper(index, current_weight, current_value):
nonlocal best_value
if index >= len(weights):
return
if current_weight + weights[index] <= capacity:
new_value = current_value + values[index]
best_value = max(best_value, new_value)
helper(index + 1, current_weight + weights[index], new_value)
helper(index + 1, current_weight, current_value)
helper(0, 0, 0)
return best_value
```
此方法的时间复杂度为 \( O(2^n) \),因为需要遍历所有的子集[^1]。
#### 回溯法解决01背包问题
回溯法则是一种改进版的穷尽搜索策略,在构建解决方案的过程中一旦发现当前路径不可能得到最优解,则立即停止这条路径上的探索并返回上一步继续尝试其他可能性。这种方法可以减少不必要的计算量。
```python
class Item(object):
def __init__(self, weight, value):
self.weight = weight
self.value = value
def backtrack_knapsack(items, capacity):
items.sort(key=lambda item: item.value / item.weight, reverse=True)
result = []
total_value = 0
remaining_capacity = capacity
def search(current_index, path, accumulated_value):
nonlocal total_value, result, remaining_capacity
if current_index == len(items) or not remaining_capacity > 0:
if accumulated_value > total_value:
total_value = accumulated_value
result[:] = path[:]
return
# 不选第current_index件商品
search(current_index + 1, path[:], accumulated_value)
# 如果还能放下这件商品就选它
if items[current_index].weight <= remaining_capacity:
updated_path = path[:] + [items[current_index]]
updated_accumulated_value = accumulated_value + items[current_index].value
updated_remaining_capacity = remaining_capacity - items[current_index].weight
search(
current_index + 1,
updated_path,
updated_accumulated_value
)
search(0, [], 0)
return (total_value, result)
```
该算法平均情况下优于蛮力法,但在最坏情况下的时间复杂度仍接近于 \( O(n*2^n) \)[^2]。
#### 动态规划解决01背包问题
动态规划利用了重叠子问题特性,避免重复计算相同的状态转移过程。具体来说就是建立一个二维数组 `dp` 来保存不同阶段的最大价值:
- 行代表考虑前 i 项物品;
- 列表示剩余空间 j 下能达到的最大总价值;
状态转换方程如下所示:
\[ dp[i][j]=\begin{cases}
max(dp[i−1][j],dp[i−1][j-w_i]+v_i)&,\text{j}≥w_i\\
dp[i−1][j]&,\text{j}<w_i
\end{cases}\]
其中 \( w_i \) 和 \( v_i \) 分别指代第 i 个物体的质量及其对应的价值。
```python
def knapsack_dp(weights, values, W):
N = len(values)
K = [[0 for _ in range(W + 1)] for _ in range(N + 1)]
for i in range(N + 1):
for w in range(W + 1):
if i == 0 or w == 0:
K[i][w] = 0
elif weights[i - 1] <= w:
K[i][w] = max(K[i - 1][w],
K[i - 1][w - weights[i - 1]] + values[i - 1])
else:
K[i][w] = K[i - 1][w]
res = K[N][W]
w = W
selected_items = []
for i in range(N, 0, -1):
if res <= 0:
break
if res != K[i - 1][w]:
selected_items.append((weights[i - 1], values[i - 1]))
res -= values[i - 1]
w -= weights[i - 1]
return sum([item[1] for item in selected_items]), list(reversed(selected_items))
```
这种做法能够有效地降低时间开销至线性级别即 \( O(nc) \),这里 c 是指给定容器的最大承重量[^3]。
阅读全文