P1048 [NOIP2005 普及组] 采药

[NOIP2005]采药

辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:"孩子,这个山洞里有一些不同的草药(共 m 株),采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。"

现在已知山洞中共有 n 株草药,采第 i 株采药需要花费 t[i] 时间,可以获得 c[i] 价值。

采药的时间 T(1≤T≤1000) ,一共有不超过 100 个草药,每个草药的价值和消耗的时间不超100 。

我们可以看出这是一道 01 背包 的题目,可以设 f[j] 表示消耗时间为 j 时可以获得的最大价值和,然后进行通过递推进行转移:

cpp 复制代码
for (int i = 1; i <= n; i++) {
    for (int j = T; j >= t[i]; j--) {
        f[j] = max(f[j], f[j - t[i]] + c[i]);
    }
}
cout << f[T] << endl;

实际上我们还可以通过dfs求解小数据时的答案。设

cpp 复制代码
void dfs(int x, int sumt, int sumc)

表示在前 1∼(x−1) 株药草中,已经花费了 sumt 的时间,采了 sumc 价值的药。

cpp 复制代码
int n, T;
int dfs(int x, int sumt) {
    if (x > n) return 0;
    int r = 0;
    if (sumt + t[x] <= T) {
        r = dfs(x + 1, sumt + t[x]) + c[x];
    }
    r = max(r, dfs(x + 1, sumt));
    return r;
}

cout << dfs(1, 0);

我们尝试用记忆化搜索的方式来求解这个动态规划方程。

我们用 f[i][j] 表示在 i,i+1,⋯,n−1,n 中选择物品,剩余时间为 j 时能选出的最大价值和。

然后 DFS 时每次枚举某一个物品选择或者不选,当某些状态已经得到答案时,可以直接返回结果。

cpp 复制代码
int n, T, f[101][1001];
int dfs(int x, int sumt) {
    if (x > n) return 0;
    if (f[x][sumt] != -1) return f[x][sumt];
    int r = 0;
    if (sumt + t[x] <= T) {
        r = dfs(x + 1, sumt + t[x]) + c[x];
    }
    r = max(r, dfs(x + 1, sumt));
    return f[x][sumt] = r;
}

cout << dfs(1, 0);
完整代码
cpp 复制代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int t[101], c[101], n, f[101][1001], T; // t[i] 为耗费的时间, c[i] 为价值
int dfs(int x, int sumt) {
    if (x > n) return 0;
    if (f[x][sumt] != -1) return f[x][sumt];
    int r = 0;
    if (sumt + t[x] <= T) {
        r = dfs(x + 1, sumt + t[x]) + c[x];
    }
    r = max(r, dfs(x + 1, sumt));
    return f[x][sumt] = r;
}

int main() {
    scanf("%d%d", &T, &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &t[i], &c[i]);
    }
    memset(f, -1, sizeof(f)); // 将所有状态初始化为未计算
    printf("%d\n", dfs(1, 0));
    return 0;
}
相关推荐
AI成长日志6 分钟前
【算法学习专栏】动态规划基础·中等两题精讲(198.打家劫舍、322.零钱兑换)
学习·算法·动态规划
计算机安禾8 分钟前
【数据结构与算法】第28篇:平衡二叉树(AVL树)
开发语言·数据结构·数据库·线性代数·算法·矩阵·visual studio
测试_AI_一辰8 分钟前
AI 如何参与 Playwright 自动化维护:一次自动修复闭环实践
人工智能·算法·ai·自动化·ai编程
未来之窗软件服务22 分钟前
算法设计—计算机等级考试—软件设计师考前备忘录—东方仙盟
算法·软件设计师·计算机等级考试
未来之窗软件服务24 分钟前
哈夫曼树构造—计算机等级考试—软件设计师考前备忘录—东方仙盟
算法·软件设计师·计算机等级考试·仙盟创梦ide·东方仙盟
kpl_201 小时前
智能指针(C++)
c++·c++11·智能指针
SUNNY_SHUN1 小时前
VLM走进农田:AgriChat覆盖3000+作物品类,607K农业视觉问答基准开源
论文阅读·人工智能·算法·开源
黎阳之光1 小时前
视频孪生赋能车路云一体化,领跑智慧高速新征程
人工智能·算法·安全·数字孪生
Darkwanderor1 小时前
高精度计算——基础模板整理
c++·算法·高精度计算
普马萨特2 小时前
基站 / WiFi 粗略位置对 A-GNSS 的影响
网络·人工智能·算法