这道题目来自XTUOJ(湘潭大学在线评测系统)的第1436题,题目名为"礼物"。从标题和描述来看,这是一个典型的背包问题变种,要求使用深度优先搜索(DFS)算法来解决。
背包问题是算法竞赛中的经典题型,主要考察选手对动态规划或搜索算法的掌握程度。01背包特指每种物品只能选择取或不取(即0或1)的情况。虽然常规解法是用动态规划,但题目特别注明"我用dfs",说明需要探讨如何用深度优先搜索来解决这类问题。
虽然原题描述未给出,但根据"礼物"和"01背包"关键词,可以合理还原题目:
有N件礼物,每件礼物有重量w[i]和价值v[i]。给定背包容量W,要求选择若干礼物装入背包,使得总重量不超过W,且总价值最大。每件礼物只能选择取或不取。
用DFS解决01背包问题的核心思想是:
python复制max_value = 0
def dfs(index, current_weight, current_value):
global max_value
if current_weight > W:
return
if index == N:
if current_value > max_value:
max_value = current_value
return
# 选择当前礼物
dfs(index+1, current_weight + w[index], current_value + v[index])
# 不选当前礼物
dfs(index+1, current_weight, current_value)
dfs(0, 0, 0)
print(max_value)
这种基础DFS的时间复杂度是O(2^N),因为每个礼物都有选或不选两种可能。对于N=20时,2^20≈1e6,尚可接受;但当N=30时,2^30≈1e9,就会超时。
可以通过以下剪枝策略提升效率:
python复制# 预处理后缀和
suffix_sum = [0]*(N+1)
for i in range(N-1, -1, -1):
suffix_sum[i] = suffix_sum[i+1] + v[i]
def dfs(index, current_weight, current_value):
global max_value
if current_weight > W:
return
if current_value + suffix_sum[index] <= max_value:
return
if index == N:
if current_value > max_value:
max_value = current_value
return
dfs(index+1, current_weight + w[index], current_value + v[index])
dfs(index+1, current_weight, current_value)
虽然纯01背包问题不适合记忆化(因为状态由index和current_weight决定,后者范围可能很大),但当W较小时可以考虑:
python复制from functools import lru_cache
@lru_cache(maxsize=None)
def dfs(index, remaining_weight):
if index == N or remaining_weight == 0:
return 0
if w[index] > remaining_weight:
return dfs(index+1, remaining_weight)
return max(
dfs(index+1, remaining_weight),
dfs(index+1, remaining_weight - w[index]) + v[index]
)
传统01背包DP解法:
python复制dp = [0]*(W+1)
for i in range(N):
for j in range(W, w[i]-1, -1):
dp[j] = max(dp[j], dp[j-w[i]] + v[i])
print(dp[W])
XTUOJ的典型输入格式:
python复制import sys
def input():
return sys.stdin.readline()
T = int(input())
for _ in range(T):
N, W = map(int, input().split())
w = []
v = []
for _ in range(N):
wi, vi = map(int, input().split())
w.append(wi)
v.append(vi)
# 调用解题函数
假设N=20,W=100:
当N=25时:
如果题目改为"恰好装满背包":
如果礼物数量无限(完全背包):
用DFS解决01背包问题虽然不如DP高效,但在特定场景下有其优势:
在实际编程竞赛中,建议:
最后分享一个调试技巧:在XTUOJ上遇到WA时,可以生成小随机数据对拍DFS和DP解法,快速定位错误。