P1048 [NOIP2005 普及组] 采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
1.代码
#include <iostream>
#include <algorithm>
using namespace std;
struct Herb
{
int time;
int value;
};
int main()
{
int T, M;
cin >> T >> M;
Herb herbs[1001];
for (int i = 1; i <=M; i++)
{
cin >> herbs[i].time >> herbs[i].value;
}
int dp[101][1001];
for (int i = 0; i <= M; ++i)
{
for (int j = 0; j <= T; ++j)
{
if (i == 0 || j == 0)
{
dp[i][j] = 0;
}
else if (herbs[i].time > j)
{
dp[i][j] = dp[i - 1][j];
}
else
{
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - herbs[i].time] + herbs[i].value);
}
}
}
cout << dp[M][T] << endl;
return 0;
}
2.思路
dp
定义数组dp[100][100],如果尝试访问 dp[100][...]
或 dp[...][100]
,就会超出数组的有效索引范围。在 C++ 中,数组的索引范围是从 0
到 数组大小 - 1
。对于 dp[100][100]
,有效的索引范围是 0
到 99
。如果你尝试访问 dp[100][...]
,就会导致数组越界。同样,如果尝试访问 dp[...][100]
,也会导致数组越界。
if (i == 0 || j == 0)
:这个条件判断语句检查是否处于动态规划表格的边界。i
表示草药的编号,j
表示时间。当 i
或 j
等于 0 时,意味着我们还没有考虑任何一株草药或者时间为 0。在这两种情况下,我们将 dp[i][j]
设置为 0。
P1616 疯狂的采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
struct Herb
{
int time;
int value;
};
signed main()
{
int T, M;
cin >> T >> M;
Herb herbs[100010];
for (int i = 1; i <= M; ++i)
{
cin >> herbs[i].time >> herbs[i].value;
}
int dp[10000010] = { 0 };
for (int i = 1; i <= M; ++i)
{
for (int j = herbs[i].time; j <= T; ++j)
{
dp[j] = max(dp[j], dp[j - herbs[i].time] + herbs[i].value);
}
}
cout << dp[T] << endl;
return 0;
}
P1049 [NOIP2001 普及组] 装箱问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <iostream>
using namespace std;
#define int long long
signed main() {
int m, n;
cin >> m >> n;
int w[101];
int dp[101][20010] = {0};
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
dp[i][j] = dp[i - 1][j];
if (j >= w[i]) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - w[i]] + w[i]);
}
}
}
cout << m - dp[n][m] << endl;
return 0;
}