题解:洛谷 P1616 疯狂的采药

【题目来源】

洛谷:P1616 疯狂的采药 - 洛谷

【题目描述】

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

如果你是 LiYuxiang,你能完成这个任务吗?

此题和原题的不同点:

\(1\). 每种草药可以无限制地疯狂采摘。

\(2\). 药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!

【输入】

输入第一行有两个整数,分别代表总共能够用来采药的时间 \(t\) 和代表山洞里的草药的数目 \(m\)

\(2\) 到第 \((m + 1)\) 行,每行两个整数,第 \((i + 1)\) 行的整数 \(a_i, b_i\) 分别表示采摘第 \(i\) 种草药的时间和该草药的价值。

【输出】

输出一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

【输入样例】

70 3
71 100
69 1
1 2

【输出样例】

140

【算法标签】

《洛谷 P1616 采药》 #动态规划DP# #背包DP# #洛谷原创#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

#define int long long  // 使用长整型防止溢出
const int N = 10005;   // 定义最大物品数量
const int M = 10000005; // 定义最大时间限制

int t;                  // 总可用时间
int m;                  // 草药种类数量
int a[N];               // 存储每种草药采摘所需的时间
int b[N];               // 存储每种草药的价值
int f[M];               // 动态规划数组,f[j]表示在时间j内能获得的最大价值

signed main()  // 使用signed代替int(因为定义了#define int long long)
{
    // 输入总时间和草药种类数
    cin >> t >> m;
  
    // 输入每种草药的采摘时间和价值
    for (int i = 1; i <= m; i++)
    {
        cin >> a[i] >> b[i];
    }
  
    // 完全背包问题:动态规划求解
    for (int i = 1; i <= m; i++)
    {
        // 遍历所有可能的时间(从当前草药所需时间到总时间)
        for (int j = a[i]; j <= t; j++)
        {
            // 状态转移方程:
            // 选择采摘当前草药:f[j] = max(不采摘, 采摘当前草药 + 剩余时间的最大价值)
            f[j] = max(f[j], f[j - a[i]] + b[i]);
        }
    }
  
    // 输出在总时间t内能获得的最大价值
    cout << f[t] << endl;
  
    return 0;
}

【运行结果】

70 3
71 100
69 1
1 2
140
posted @ 2026-02-19 21:59  团爸讲算法  阅读(2)  评论(0)    收藏  举报