机器人饲养指南
用完全背包式 DP 枚举最后一天投喂的苹果数,求恰好投喂 n 个苹果的最大收益。
OJ: shumeng
题目 ID: CSP202503B
难度:普及-
标签:动态规划完全背包
日期: 2026-07-31 16:21
形式化题目
有
思路
每一天投喂的数量在
朴素递归
先看一个直接枚举每天投喂数量的递归做法,它把问题拆成一层一层的选择:
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-07-31 16:21
* update_at: 2026-08-17 22:47
*/
// brute.cpp:小数据暴力解,用来帮助理解题意并辅助对拍。
#include <bits/stdc++.h>
using namespace std;
int n, m;
vector<long long> happiness;
// 递归枚举每天投喂的苹果数,remaining 表示还剩多少个苹果
long long dfs(int remaining) {
if (remaining == 0) return 0;
long long answer = -(1LL << 60);
for (int today = 1; today <= min(m, remaining); today++) {
answer = max(answer, happiness[today] + dfs(remaining - today));
}
return answer;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
happiness.assign(m + 1, 0);
for (int i = 1; i <= m; i++) cin >> happiness[i];
cout << dfs(n) << '\n';
return 0;
}递归中每天都枚举投喂
动态规划
设
初值
代码
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-07-31 16:21
* update_at: 2026-08-17 22:47
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<long long> happiness(m + 1, 0); // happiness[i] 表示一天投喂 i 个苹果的快乐值
for (int i = 1; i <= m; i++) cin >> happiness[i];
// dp[i] 表示恰好投喂 i 个苹果能获得的最大快乐值
vector<long long> dp(n + 1, -(1LL << 60));
dp[0] = 0;
for (int apples = 1; apples <= n; apples++) {
// 最后一天投喂 today 个,前面已经投喂 apples-today 个
int limit = min(m, apples);
for (int today = 1; today <= limit; today++) {
dp[apples] = max(dp[apples], dp[apples - today] + happiness[today]);
}
}
cout << dp[n] << '\n';
return 0;
}复杂度
每个状态
总结
每天的收益