问题描述:有个容量为m的背包和n∈[1, 100]个物品,每个物品的重量为w[i]∈[1, 100],价格为p[i]∈[1, 100],问如何装入物品,使得在不超过背包容量的情况下,使得装下的物品的价格最大?
这题有三种解法,咱们先介绍动态规划的解法。
构造一个一维数组f[10005],f[i]表示背包容量为i时,背包里的物品价格的最大值
于是我们有递推式f[i] = max( f[i], f[i - w] + p);
采用自顶而下的遍历
#include <bits/stdc++.h>
using namespace std;
int f[10005];
int main()
{
int w[105], p[105], n, m;
while(~scanf("%d%d", &n, &m) && n) {
memset(w, 0, sizeof(w));
memset(p, 0, sizeof(p));
memset(f, 0, sizeof(f));
for(int i = 0;i < n; ++i) scanf("%d%d", &w[i], &p[i]);
for(int i = 0;i < n; ++i)
for(int j = m;j >= w[i]; --j)
f[j] = max(f[j], f[j - w[i]] + p[i]);
printf("%d\n", f[m]);
}
return 0;
}
第二种是用递归法,跟动态规划相似的思路。
也是自顶而下的。
#include <bits/stdc++.h>
using namespace std;
int n, w[105], p[105];
void solve(int index, int free_space)
{
if(index < 0 || free_space <= 0) return 0;
int ret = solve(index - 1, free_space);
if(w[index]<=free_space) ret=max(ret,solve(index-1,free_space-w[index]));
return ret;
}
int main()
{
while(~scanf("%d%d", &n, &m)) {
memset(w, 0, sizeof(w));
memset(p, 0, sizeof(p));
for(int i = 0;i < n; ++i) scanf("%d%d", &w[i], &p[i]);
printf("%d\n", solve(n - 1, m));
}
}
优化下递归就成了记忆化搜索。
#include <bits/stdc++.h>
using namespace std;
int n, w[105], p[105], me[105][105];
void solve(int index, int free_space)
{
if(index < 0 || free_space <= 0) return 0;
if(me[index][free_space]) return me[index][free_space];
int ret = solve(index - 1, free_space);
if(w[index]<=free_space) ret=max(ret,solve(index-1,free_space-w[index]));
me[index][free_space] = ret;
return ret;
}
int main()
{
while(~scanf("%d%d", &n, &m)) {
memset(w, 0, sizeof(w));
memset(p, 0, sizeof(p));
memset(me, 0, sizeof(me));
for(int i = 0;i < n; ++i) scanf("%d%d", &w[i], &p[i]);
printf("%d\n", solve(n - 1, m));
}
}
原文:https://www.cnblogs.com/xdaniel/p/12260206.html