01背包问题:
这个问题在大一的时候就接触了,差不多一年后才恍然大悟, 哎难受。。。。
题目是这样描述的:有一个容量为V的背包,有n个物品, 每个物品的的价值为val[i] ,体积为w[i],求背包能装的物品 使得物品的总价值最高。
注意:01背包问题是指每个物品只有两种状态,1表示取,0表示不取。
用一个二维数组表示 dp[i][j] 表示放进的第i个物品,背包剩余容积为j时,此时所得的最大价值。状态转移方程为:dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
下面详细的解释一下这个方程:dp[i][j] 表示放进的第i个物品,背包剩余容积为j时,此时所得的最大价值 而dp[i][j]又是通过dp[i-1][j]推来的 ,如果不放第i个物品则可以表示为dp[i-1][j],如果放第i个物品则可以表示为dp[i-1][j-c[i]]+w[i],而到底取不取第i个物品取决于 两者的价值。
下面附上代码:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n,V;
int val[100],w[100],dp[100][100];
cin>>n>>V;
for(int i =1; i<=n; i++)
cin>>val[i]>>w[i];
memset(dp,0,sizeof(dp));
for(int i =1;i<=n;i++)
{
for(int j=0;j<=V;j++)
{
if(j>=val[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-val[i]]+w[i]);
else
dp[i][j]=dp[i-1][j];
}
}
cout<<dp[n][V];
}
上面那种dp开的是一个二维数组,其实并不需要,特别浪费空间 如果数据开大一点就会爆,下面附上用一维数组的做法:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n,V;
int val[100],w[100],dp[100];
cin>>n>>V;
for(int i =1; i<=n; i++)
cin>>val[i]>>w[i];
memset(dp,0,sizeof(dp));
for(int j =1;j<=n;j++)
for(int i=V;i>=val[j];i--)
dp[i]=max(dp[i],dp[i-val[j]]+w[j]);
cout<<dp[V];
}