有一个背包有5容量(重量),有4种宝石重量和价值分别为2 5;1 2;2 3;5 6;
0 | 1 | 2 | 3 | 4 | 5 | |
1 | 0 | 0 | 5 | 5 | 5 | 5 |
2 | 0 | 2 | 5 | 7 | 7 | 7 |
3 | 0 | 2 | 5 | 7 | 8 | 10 |
4 | 0 | 2 | 5 | 7 | 8 | 10 |
其实01背包就是一种所有情况的举例,例如上面:将背包容量只有0 1 2 3 4 5时能装下的宝石的价值全部举例.
从第3个宝石开始:当背包能装下5重量的宝石时:
1.若装第三种宝石则还剩下3个容量,dp[3][5]=dp[2][3]+v[3] (dp[2][3]以此类推如果装第二种宝石dp[2][3]=dp[1][2]+v[2]如果不装则dp[2][3]=dp[1][3]最终dp[2][3]=其中较大的那个;dp[1][2]或dp[1][3]以此类推)//dp[2][3]包含了是否装第一,二种宝石所有情况中的最大价值 )。
2.如果不装第三种宝石 则dp[3][5]=dp[2][5] 价值dp[2][5]和上面同样推法
上面表格中dp[3][5]=dp[2][3]+v[3]=dp[1][2]+v[2]+v[3];dp[1][2]
o1背包算法题:
一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是W_1,W_2,...,W_n,它们的价值分别为C_1,C_2,...,C_n,求旅行者能获得最大总价值。
输入描述
第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30);
第2..N+1行:每行二个整数W_i,C_i,表示每个物品的重量和价值。
输出描述
仅一行,一个数,表示最大总价值。
用例输入 1 输出:12
10 4 2 1 3 3 4 5 7 9
二维代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int dp[N][N];//定义背包数组
int main(){
int n,m;
cin>>m>>n;
for(int i=1;i<=n;i++){
cin>>w[i]>>v[i];分别输入每一种物品的重量和价值
}
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
dp[i][j]=dp[i-1][j];
if(j>=w[i]) dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]]+v[i]);//进行比较如果放入此物品或不放入此物品哪种的价值更高
}
}
cout<<dp[n][m];
}
dp[0] dp[1] dp[2] dp[3] dp[4] dp[5] 1 0 0 5 5 5 5 2 0/0 0/2 5/5 5/7 5/7 5/7 3 4 因为所有宝石共用一个一维数组dp[0]到dp[5],所以以二维数组类推dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]]+v[i]);这里的dp[i][j]数据=dp[i],第二种宝石经过变换dp[0]到dp[5]变成了红色数据
此题一维解法
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int dp[N];
int main(){
int n,m;
cin>>m>>n;
for(int i=1;i<=n;i++){
cin>>w[i]>>v[i];
}
for(int i=1;i<=n;i++){
for(int j=m;j>=w[i];j--){//一维数组要采用倒叙,防止影响后面的数据
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
cout<<dp[m];
}