一、问题描述:
给定一组物品,给出每种物品的价值和重量,每种物品足够多,在限定重量内,如何选择,才能使物品总价值最高
二、解决方案:
设
f
(
x
)
表
示
重
量
不
超
过
x
千
克
的
最
大
价
值
,
则
:
设f(x)表示重量不超过x千克的最大价值,则:
设f(x)表示重量不超过x千克的最大价值,则:
f
(
x
)
=
m
a
x
{
f
(
x
−
w
e
i
g
h
t
[
i
]
)
+
v
a
l
u
e
[
i
]
}
f(x) = max\{f(x - weight[i]) + value[i]\}
f(x)=max{f(x−weight[i])+value[i]}
(
x
≥
w
e
i
g
h
t
[
i
]
,
1
≤
i
≤
n
)
(x \geq weight[i],1 \leq i \leq n)
(x≥weight[i],1≤i≤n)
三、代码:
// TSWorld
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const long long MAXX = 1000;
int main()
{
int M = 0,N = 0;
int weight[MAXX] = {0},value[MAXX] = {0};
int f[MAXX] = {0};
cin>>N>>M;
for(int i = 1;i <= N;i++)
cin>>weight[i]>>value[i];
for(int i = 1;i <= M;i++) {
for(int j = 1;j <= N;j++) {
if(i >= weight[j]) {
f[i] = max(f[i-weight[j]]+value[j],f[i]);
}
}
}
cout<<f[M]<<endl;
return 0;
}
四、完全背包算法优化:
4.1 思路分析:
可以用一个数组
f
[
m
]
f[m]
f[m]来解决,数组下标表示包的最大承重,
f
[
m
]
f[m]
f[m]数值表示该承重下放的最大价值。可以代替
w
e
i
g
h
t
[
N
]
weight[N]
weight[N]和
v
a
l
u
e
[
N
]
value[N]
value[N]数组,时间复杂度未优化。
动态转移方程:
f
(
x
)
=
m
a
x
(
f
(
x
−
w
e
i
g
h
t
)
+
v
a
l
u
e
,
f
(
x
)
)
f(x) = max(f(x - weight) + value,f(x))
f(x)=max(f(x−weight)+value,f(x))
显然只要M足够大,就可以放无限个该物品
4.2 代码:
// TSWorld
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const long long MAXX = 1000;
int main()
{
int M = 0,N = 0;
int weight = 0,value = 0;
int f[MAXX] = {0};
cin>>N>>M;
for(int i = 1;i <= N;i++) {
cin>>weight>>value;
for(int j = weight;j <= M;j++)
f[j] = max(f[j-weight] + value,f[j]);
}
cout<<f[M]<<endl;
return 0;
}
五、0/1背包算法的优化:
5.1 思路分析:
搜索方向从后向前,每次计算都会用到小于当前下标的数据,所以即使后边的下标放入该物品,前面的下标并没有放置,因此计算出来的数据每个物品最多只能放一个,也就是所谓的0/1背包问题。显然,该代码与前面代码几乎完全一致,只是一个是从前向后计算,一个是从后向前计算,但是无论是时间复杂度,空间复杂度,程序复杂度和记忆复杂度均优于最初算法。5.2 代码:
// TSWorld
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const long long MAXX = 1000;
int main()
{
int M = 0,N = 0;
int weight = 0,value = 0;
int f[MAXX] = {0};
cin>>N>>M;
for(int i = 1;i <= N;i++) {
cin>>weight>>value;
for(int j = M;j >= weight;j--)
f[j] = max(f[j-weight] + value,f[j]);
}
cout<<f[M]<<endl;
return 0;
}