- 01背包问题
问题描述:有N件物品,每件物品的重量为w[i],价值为c[i],现有一个容量为V的背包,问如何选取物品放入背包中,使得物品的总价值最大。其中每种物品都只有1件。
输入:
5 8 //物品数 最大容量
3 4 //每件物品的重量 每件物品的价值
5 5
1 2
2 1
2 3
输出:10 - 完全背包问题
问题描述:有N件物品,每件物品的重量为w[i],价值为c[i],现有一个容量为V的背包,问如何选取物品放入背包中,使得物品的总价值最大。其中每种物品都有无穷件。
输入:
5 8
3 4
5 5
1 2
2 1
2 3
输出:16
//背包问题
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100
int c[MAXN],w[MAXN];//c:存储价值 w存储消耗的容量
int dp[MAXN][MAXN];//第一维:标号 第几件物品 第二维:当前容量
// 整个DP数组表示的值是前i件物品恰好装入容量为v的背包中所能获得的最大价值
int V,N;
int main()
{
cin>>N>>V;
for(int i=1;i<=N;i++)
{
cin>>w[i]>>c[i];//从1开始输入,0当作第一个的前面边界,为0
}
//dp[0][k]为边界,若定义的局部变量应赋值为0,但此处为全局变量,已经初始化
for(int i=1;i<=N;i++)
{
for(int k=0;k<=V;k++) //从0开始枚举容量 ,恰好装入容量为K,其获得的最大值 // 其实从W[i]开始枚举即可 此时无需下面的if判断
{
dp[i][k]=dp[i-1][k];//继承上一个的 最大价值及消耗的容量
if(k>=w[i])//当前拥有容量大于消耗的容量
{
dp[i][k]=max(dp[i][k],dp[i-1][k-w[i]]+c[i]);//两种策略 不放第i件物品 和放入第i件物品
} //将上述改为 max(dp[i][k],dp[i][k-w[i]]+c[i]);即为完全背包问题
//后面为放入i的转移策略,在完全背包中,放入i后还可以放入 i物品,故将i-1改为i即可
}
}
//最后应找到所有容量中最大价值值,故应该枚举容量找到最大值,但其实上述有继承效果,最大的dp[最后一件物品][最大容量]即为最大值
cout<<dp[N][V]<<endl;
return 0;
}
//背包问题 上述为正确方法,这种方法有误--------------------------------------
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100
int c[MAXN],w[MAXN];//c:存储价值 w存储消耗的容量
int dp[MAXN][MAXN];//第一维:标号 第几件物品 第二维:当前容量
// 整个DP数组表示的值是前i件物品恰好装入容量为v的背包中所能获得的最大价值
int V,N;
int main()
{
cin>>N>>V;
for(int i=1;i<=N;i++)
{
cin>>w[i]>>c[i];//从1开始输入,0当作第一个的前面边界,为0
}
//dp[0][k]为边界,若定义的局部变量应赋值为0,但此处为全局变量,已经初始化
for(int i=1;i<=N;i++)
{
for(int k=w[i];k<=V;k++) //从0开始枚举容量 ,恰好装入容量为K,其获得的最大值 // 其实从W[i]开始枚举即可 此时无需下面的if判断
{
dp[i][k]=max(dp[i-1][k],dp[i-1][k-w[i]]+c[i]);//两种策略 不放第i件物品 和放入第i件物品
//将上述改为 max(dp[i][k],dp[i][k-w[i]]+c[i]);即为完全背包问题
//后面为放入i的转移策略,在完全背包中,放入i后还可以放入 i物品,故将i-1改为i即可
}
}
//最后应找到所有容量中最大价值值,故应该枚举容量找到最大值,但其实上述有继承效果,最大的dp[最后一件物品][最大容量]即为最大值
cout<<dp[N][V]<<endl;
return 0;
}
当输入5 10
5 6
5 7
2 8
8 1
5 9
结果为15
正确结果应当为17
打表,横坐标为容量递增,纵坐标为第i件物品
问题出在第二层容量循环
正确结果: