01背包
问题描述
已知:有一个容量为 V 的背包和 N 件物品,第 i 件物品的重量是 weight[ i ],收益是 cost[ i ]。
限制:每种物品只有一件,可以选择放或者不放
问题:在不超过背包容量的情况下,最多能获得多少价值或收益
相似问题:在恰好装满背包的情况下,最多能获得多少价值或收益
这里,我们先讨论在不超过背包容量的情况下,最多能获得多少价值或收益。
基本思路
01背包的特点:每种物品只有一件,可以选择放或者不放
状态转移方程:f[ i ][ v ] = max( f[ i - 1 ][ v ] , f[ i - 1 ][ v - weight[ i ] ] + cost[ i ] )
代码
1 #include <iostream> 2 using namespace std; 3 4 const int N = 3;//物品个数 5 const int V = 5;//背包最大容量 6 int weight[N + 1] = {0,3,2,2};//物品重量 7 int value[N + 1] = {0,5,10,20};//物品价值 8 9 int f[N + 1][V + 1] = {{0}}; 10 11 int Max(int x,int y) 12 { 13 return x > y ? x : y; 14 } 15 16 /* 17 目标:在不超过背包容量的情况下,最多能获得多少价值 18 19 子问题状态:f[i][j]:表示前i件物品放入容量为j的背包得到的最大价值 20 21 状态转移方程:f[i][j] = max{f[i - 1][j],f[i - 1][j - weight[i]] + value[i]} 22 23 初始化:f数组全设置为0 24 */ 25 int Knapsack() 26 { 27 //初始化 28 memset(f,0,sizeof(f)); 29 //递推 30 for (int i = 1;i <= N;i++) //枚举物品 31 { 32 for (int j = 0;j <= V;j++) //枚举背包容量 33 { 34 f[i][j] = f[i - 1][j]; 35 if (j >= weight[i]) 36 { 37 f[i][j] = Max(f[i - 1][j],f[i - 1][j - weight[i]] + value[i]); 38 } 39 } 40 } 41 return f[N][V]; 42 } 43 44 int main() 45 { 46 cout<<Knapsack()<<endl; 47 return 1; 48 }
1 #include <iostream> 2 using namespace std; 3 4 const int N = 3;//物品个数 5 const int V = 5;//背包最大容量 6 int weight[N + 1] = {0,3,2,2};//物品重量 7 int value[N + 1] = {0,5,10,20};//物品价值 8 9 int f[V + 1] = {0}; 10 11 int Max(int x,int y) 12 { 13 return x > y ? x : y; 14 } 15 16 /* 17 目标:在不超过背包容量的情况下,最多能获得多少价值 18 19 子问题状态:f[j]:表示前i件物品放入容量为j的背包得到的最大价值 20 21 状态转移方程:f[j] = max{f[j],f[j - weight[i]] + value[i]} 22 23 初始化:f数组全设置为0 24 */ 25 int Knapsack() 26 { 27 //初始化 28 memset(f,0,sizeof(f)); 29 //递推 30 for (int i = 1;i <= N;i++) //枚举物品 31 { 32 for (int j = V;j >= weight[i];j--) //枚举背包容量,防越界,j下限为 weight[i] 33 { 34 f[j] = Max(f[j],f[j - weight[i]] + value[i]); 35 } 36 } 37 return f[V]; 38 } 39 40 int main() 41 { 42 cout<<Knapsack()<<endl; 43 return 1; 44 }
恰好装满
使用二维数组f[i][v]存储中间状态,其中第一维表示物品,第二维表示背包容量;初始化时,除了f[i][0] = 0(第一列)外,其他全为负无穷。
1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 31 32 32 33 33 34 34 35 35 36 36 37 37 38 38 39 39 40 40 41 41 42 42 43 43 44 44 45 45 46 46 47 47 48 48 49 49 50 50 51 51 52 52 53 53 54 54 55 55 56 56 57 57 58 58 59 59 60 60 #include <iostream> 61 using namespace std; 62 63 const int MinNum = 0x80000000; 64 65 const int N = 3;//物品个数 66 const int V = 5;//背包最大容量 67 int weight[N + 1] = {0,3,2,2};//物品重量 68 int value[N + 1] = {0,5,10,20};//物品价值 69 70 int f[N + 1][V + 1] = {{0}}; 71 72 int Max(int x,int y) 73 { 74 return x > y ? x : y; 75 } 76 77 /* 78 目标:在恰好装满背包的情况下,最多能获得多少价值 79 80 子问题状态:f[i][j]:表示前i件物品放入容量为j的背包得到的最大价值 81 82 状态转移方程:f[i][j] = max{f[i - 1][j],f[i - 1][j - weight[i]] + value[i]} 83 84 初始化:f数组全设置为0 85 */ 86 int Knapsack() 87 { 88 //初始化 89 for (int i = 0;i <= N;i++) //枚举物品 90 { 91 for (int j = 0;j <= V;j++) //枚举背包容量 92 { 93 f[i][j] = MinNum; 94 } 95 } 96 for (int i = 0;i <= N;i++) 97 { 98 f[i][0] = 0;//背包容量为0时为合法状态 99 } 100 //递推 101 for (int i = 1;i <= N;i++) //枚举物品 102 { 103 for (int j = 1;j <= V;j++) //枚举背包容量 104 { 105 f[i][j] = f[i - 1][j]; 106 if (j >= weight[i]) 107 { 108 f[i][j] = Max(f[i - 1][j],f[i - 1][j - weight[i]] + value[i]); 109 } 110 } 111 } 112 return f[N][V]; 113 } 114 115 int main() 116 { 117 cout<<Knapsack()<<endl;//输出25 118 return 1; 119 }
1 #include <iostream> 2 using namespace std; 3 4 const int MinNum = 0x80000000;//int最小的数 5 6 const int N = 3;//物品个数 7 const int V = 5;//背包最大容量 8 int weight[N + 1] = {0,3,2,2};//物品重量 9 int value[N + 1] = {0,5,10,20};//物品价值 10 11 int f[V + 1] = {0}; 12 13 int Max(int x,int y) 14 { 15 return x > y ? x : y; 16 } 17 18 /* 19 目标:在恰好装满背包容量的情况下,最多能获得多少价值 20 21 子问题状态:f[j]:表示前i件物品放入容量为j的背包得到的最大价值 22 23 状态转移方程:f[j] = max{f[j],f[j - weight[i]] + value[i]} 24 25 初始化:f数组全设置为0 26 */ 27 int Knapsack() 28 { 29 //初始化 30 for (int i = 0;i <= V;i++) 31 { 32 f[i] = MinNum; 33 } 34 f[0] = 0;//只有背包容量为0时才是合法状态,由合法状态组成的结果才是合法的 35 36 //递推 37 for (int i = 1;i <= N;i++) //枚举物品 38 { 39 for (int j = V;j >= weight[i];j--) //枚举背包容量,防越界,j下限为 weight[i] 40 { 41 f[j] = Max(f[j],f[j - weight[i]] + value[i]); 42 } 43 } 44 return f[V]; 45 } 46 47 int main() 48 { 49 cout<<Knapsack()<<endl;//输出25 50 return 1; 51 }