版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
完全背包:
假设有 n 种物品(每种物品可装入次数不限),至多可装入容积为 m 的容器当中,试问最大可装入的价值为多少?
设w[ i ]为第 i 件物品重量,v[ i ]为第i件物品价值
dp[ i ][ j ]表示将前 i 种物品装入重量 j 的容器当中
状态转移方程:
- 当i = 0 或 j = 0时,dp[ i ][ j ] = 0
- 当w[ i ] > j时,装不下,dp[ i ][ j ] = dp[ i-1 ][ j ]
- 当w[ i ] ≤ j时,设循环变量n,满足n*v[ i ] ≤ j,dp[ i ][ j ] = max( dp[ i ][ j ], dp[ i-1 ][ j-n*w[ i ]] + n*v[ i ] )
- 第2、3条可以合并,第2条等价于n=0时第3条的特例
样例输入:
- 第一行:物品种类n,最大容量m
- 第二行:每种物品重量
- 第三行:每种物品价值
3 7
3 4 2
4 5 3
样例输出:
- 最大可装入价值
10
样例代码:
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 1001//物品最大数
#define MAXM 1001//重量最大数
int dp[MAXN][MAXM];//dp数组
int w[MAXN],v[MAXN];//重量和价值数组
int n;//物品数量
int full;//最大可装重量
void solve();//解题函数
int main(){
cin>>n;//输入数量
cin>>full;//输入重量
for(int i=1;i<=n;i++){
cin>>w[i];//输入重量
}
for(int i=1;i<=n;i++){
cin>>v[i];//输入价值
}
solve();
return 0;
}
void solve(){
for(int i=0;i<=n;i++){
for(int j=0;j<=full;j++){
if(i==0 || j==0) dp[i][j]=0;//边界dp,结果为0
else{
dp[i][j]=0;//初始0
for(int n=0;n*w[i]<=j;n++){
dp[i][j]=max(dp[i][j],dp[i-1][j-n*w[i]]+n*v[i]);//大小比较
}
}
}
}
cout<<dp[n][full]<<endl;//输出结果
}
tips:
完全背包同01背包一样,可利用滚动数组进行空间优化,这里不再贴出代码,优化思路详见01背包问题