第五周
题解
1. [洛谷P1048] [NOIP2005 普及组] 采药
1-1. 题干
1-2. 解析
- 01背包,每个元素仅可以使用一次,需要逆序进行整理
1-3. 原码
#include <iostream>
using namespace std;
int t, m, ti[110], va[110];
int result[110][110];
int main()
{
cin >> t >> m;
for (int i = 1; i <= m; i++)
{
cin >> ti[i] >> va[i];
}
for (int i = 1; i <= m; i++)
{
for (int j = t; j >= 0; j--)
{
if (j >= ti[i])
{
result[i][j] = max(result[i - 1][j - ti[i]] + va[i], result[i - 1][j]);
}
else
{
result[i][j] = result[i - 1][j];
}
}
}
cout << result[m][t];
return 0;
}
2. [洛谷P1616] 疯狂的采药
2-1. 题干
2-2. 解析
2-3. 原码
#include <iostream>
using namespace std;
long long t;
int m, ti[10010], va[10010];
long long result[10000010];
int main()
{
cin >> t >> m;
for (int i = 1; i <= m; i++)
{
cin >> ti[i] >> va[i];
}
for (int i = 1; i <= m; i++)
{
for (int j = ti[i]; j <= t; j++)
{
result[j] = max(result[j - ti[i]] + va[i], result[j]);
}
}
cout << result[t];
return 0;
}
3. [洛谷P1049] [NOIP2001 普及组] 装箱问题
3-1. 题干
3-2. 解析
- 在完全背包的基础上记录所剩的空间,即判断数组中指针最小的非空数据
3-3. 原码
#include <iostream>
using namespace std;
int v, n, item[32];
bool filled[200010];
int main()
{
cin >> v >> n;
for (int i = 1; i <= n; i++)
{
cin >> item[i];
}
filled[0] = true;
for (int i = 1; i <= n; i++)
{
for (int j = v; j >= item[i]; j--)
{
filled[j] = filled[j - item[i]] || filled[j];
}
}
for (int i = 0; i <= v; i++)
{
if (filled[v - i])
{
cout << i;
return 0;
}
}
return 0;
}
4. [洛谷P1833] 樱花
4-1. 题干
4-2. 解析
- 混合背包:包括完全背包与01背包,对次数属性进行判断,无限次的元素使用完全背包进行处理,有限次的元素使用01背包进行处理
- 对于有限次的的数据的处理需要进行优化,利用2的n次幂来减少循环次数
4-3. 原码
#include <iostream>
using namespace std;
struct ti
{
int hour;
int minute;
} be, en;
struct tree
{
int t;
int c;
int p;
} tree[10010];
int n, mins, result[10010];
int main()
{
scanf("%d:%d", &be.hour, &be.minute);
scanf("%d:%d", &en.hour, &en.minute);
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d %d %d", &tree[i].t, &tree[i].c, &tree[i].p);
}
mins = (en.hour - be.hour) * 60 + (en.minute - be.minute);
for (int i = 1; i <= n; i++)
{
if (tree[i].p == 0 || tree[i].t * tree[i].p >= mins)
{
for (int j = tree[i].t; j <= mins; j++)
{
result[j] = max(result[j - tree[i].t] + tree[i].c, result[j]);
}
}
else
{
for (int j = 1; j <= tree[i].p; j *= 2)
{
for (int k = mins; k >= tree[i].t * j; k--)
{
result[k] = max(result[k - tree[i].t * j] + tree[i].c * j, result[k]);
}
tree[i].p -= j;
}
for (int j = mins; j >= tree[i].t * tree[i].p; j--)
{
result[j] = max(result[j - tree[i].t * tree[i].p] + tree[i].c * tree[i].p, result[j]);
}
}
}
printf("%d", result[mins]);
return 0;
}