01 背包入门题:dp[t] 表示 t 时间内能采到的最大总价值,每株草药倒序枚举容量完成 01 转移,O(MT) 时间、O(T) 空间。
OJ: roj
题目 ID: 3538
难度:普及-
标签:动态规划背包python
创建: 2026-10-02 06:04
更新: 2026-10-06 13:35
题目描述
山洞里有
输入格式:第一行两个整数 70 3、71 100、69 1、1 2,输出 3。
思路
这是 01 背包的定义级题目:耗时是"体积",
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 06:05
# update_at: 2026-10-02 06:05
import sys
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
T = next(data) # 总共能用来采药的时间
M = next(data) # 草药数目
# dp[t]:只用已处理过的草药、耗时不超过 t 时的最大总价值
dp = [0] * (T + 1)
for _ in range(M):
cost = next(data) # 采摘这株草药需要的时间
value = next(data) # 这株草药的价值
# 倒序枚举容量:保证 dp[cap - cost] 还是“没采过这株”的旧值
for cap in range(T, cost - 1, -1):
dp[cap] = max(dp[cap], dp[cap - cost] + value)
print(dp[T])
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 13:35
* update_at: 2026-10-06 13:35
*/
// 01 背包:dp[t] 表示总耗时不超过 t 时能采到的最大总价值
#include <iostream>
using namespace std;
typedef long long ll;
const int MAXT = 1005;
ll dp[MAXT]; // dp[t]:容量(时间)为 t 时的最大总价值
ll c[105]; // c[i]:第 i 株草药的采摘耗时
ll v[105]; // v[i]:第 i 株草药的价值
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ll T, M;
cin >> T >> M;
for (int i = 1; i <= M; i++)
cin >> c[i] >> v[i];
// 01 背包:每株草药只能采一次,容量必须倒序枚举,
// 保证 dp[t - c[i]] 还是上一轮(没采过这株)的旧值
for (int i = 1; i <= M; i++)
for (ll t = T; t >= c[i]; t--)
if (dp[t - c[i]] + v[i] > dp[t])
dp[t] = dp[t - c[i]] + v[i];
cout << dp[T] << endl;
return 0;
}