1. 问题分析与解题思路
这道题目本质上是一个经典的0-1背包问题变种。我们需要在有限的工作时间内(背包容量),选择一组工作(物品),使得总报酬(价值)最大化,同时不超过总工作时长限制(背包容量限制)。
1.1 问题建模
我们可以将问题抽象为:
- 容量限制:总工作时长T
- 物品集合:n个工作,每个工作有耗时t和报酬w
- 目标:选择工作子集,使得总耗时≤T,且总报酬最大
1.2 算法选择
对于这类问题,常见的解法有:
- 暴力枚举:时间复杂度O(2^n),n=3000时完全不可行
- 动态规划:时间复杂度O(n*T),在本题参数范围内可行
- 贪心算法:无法保证最优解
考虑到题目给出的数据范围(T<100000,n<3000),动态规划是最合适的选择。我们可以使用经典的0-1背包DP解法。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动态规划解法详解
2.1 DP状态定义
定义dp[i][j]表示考虑前i个工作,总时长为j时能获得的最大报酬。
2.2 状态转移方程
对于每个工作i,我们有两种选择:
- 不选这个工作:dp[i][j] = dp[i-1][j]
- 选这个工作:dp[i][j] = dp[i-1][j-t_i] + w_i
因此状态转移方程为:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-t_i] + w_i)
2.3 初始化
dp[0][j] = 0 (没有工作时报酬为0)
dp[i][0] = 0 (工作时长为0时报酬为0)
2.4 空间优化
由于dp[i]只依赖于dp[i-1],可以使用一维数组优化空间:
dp[j] = max(dp[j], dp[j-t_i] + w_i)
注意需要从后向前遍历j,避免覆盖之前的状态。
3. 代码实现与解析
3.1 Python实现
python复制def max_reward(T, n, jobs):
dp = [0] * (T + 1)
for t, w in jobs:
for j in range(T, t - 1, -1):
dp[j] = max(dp[j], dp[j - t] + w)
return dp[T]
