蒜头君去超市购物,他有一只容量为V的购物袋,同时他想买n件物品,已知每件物品的体积 vi和重要度pi 。蒜头君想知道,挑选哪些物品放入购物袋中,可以使得买到的物品重要度之和最大,且物品体积和不超过购物袋的容量。
输入格式
第一行输入两个整数V(1≤V≤1000)和n(1≤n≤100)。代表购物袋的总体积为V,蒜头君一共想买n件物品。
接下来输入n 行,每行输入两个整数 vi 和 pi(1≤vi,pi≤100),分别表示每件物品的体积和重要度。
输出格式
输出一行,输出一个整数,表示蒜头君能买到物品的最大重要度之和。
样例输入
50 4
1 5
60 99
49 8
33 7
样例输出
13
二维数组解法:
用dp[i][j]表示取前i种物品,是他们总体积不超过j的最优取法取得的价值总和。
状态转移方程dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+p[i]);(两种情况:1.不取第i种物品,则dp[i][j]是dp[i-1][j];2.取第i种物品,背包剩余体积减去第i种物品的体积w[i],并且加上第i种的价值,这种情况必须是第i种物品体积不超过背包剩余体积)
#include<iostream>
#include<algorithm>
using namespace std;
int dp[1005][1005],w[105],p[105];
int main(){
int v,n;
cin>>v>>n;
for(int i=1;i<=n;i++){
cin>>w[i]>>p[i];
}
for(int i=1;i<=n;i++)
for(int j=0;j<=v;j++){
if(j>=w[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+p[i]);
else
dp[i][j]=dp[i-1][j];
}
cout<<dp[n][v]<<endl;
return 0;
}
优化空间复杂度:
当计算第i件物品,总重量不超过v时,他所需要的状态是dp[i-1][0...v],(即计算第i行第j列只需要它上面一行j列左面的数),所以我们可以将二维数组转化为一维数组,优化空间复杂度。因为求第j列会用到它上面及左边的数,所以我们在计算一行时选择从右向左计算,即先计算dp[v],用它覆盖上一行的dp[v],再计算dp[v-1...0],状态转移方程可以简化为:dp[j]=max(dp[j−w[i]]+v[i],dp[j])
#include<iostream>
#include<algorithm>
using namespace std;
int dp[1005],w[105],p[105];
int main(){
int v,n;
cin>>v>>n;
for(int i=1;i<=n;i++){
cin>>w[i]>>p[i];
}
for(int i=1;i<=n;i++)
for(int j=v;j>=w[i];j--)
dp[j]=max(dp[j-w[i]]+p[i],dp[j]);
cout<<dp[v]<<endl;
return 0;
}