二维数组构成以及回溯
#include <iostream> #include <vector> #include <algorithm> using namespace std; const int MAXN = 10010; //定义最大物品的数量 const int MAXV = 10010; //定义最大背包的容量 int N; //储存物品数量 int V; //定义背包的容量 int w[MAXN]; // 储存每件物品的重量w[i] int c[MAXV]; //储存每件物品的价值c[i] int dp[MAXN][MAXV]; //二维dp数组 vector<int> choose; //定义存储方案(用于回溯) void knapsack() { //边界处理 for (int i = 0; i <= V; i++) dp[0][i] = 0; //状态更新 for (int i = 1; i <= N; i++) for (int v = 0; v <= V; v++) { if (v >= w[i]) dp[i][v] = max(c[i] + dp[i - 1][v - w[i]], dp[i - 1][v]); //能放得下第i件物品 else dp[i][v] = dp[i - 1][v]; //放不下第i件物品 } } //回溯 void flashback() { int i = N, j = V; while (j != 0) //因为是从最大的开始回溯,什么时候截止呢?在j=0或i=0时截止,j=0时,是没有容量了,i=0时是没有物品了 { if (dp[i][j] == dp[i - 1][j]) //情况1:没有选择第i件物品 i--; else { choose.push_back(i); //情况2:选择了第i件物品 j = j - w[i]; i--; } } } int main() { cin >> N >> V; //输入物品个数和最大的背包容量 for (int i = 1; i <= N; i++) cin >> w[i]; for (int i = 1; i <= N; i++) cin >> c[i]; knapsack(); flashback(); //回溯 cout << endl << dp[N][V] << endl; //输出最大值 for (int i = choose.size() - 1; i >= 0; i--) //因为vector先存的是编号大的数,现在要把编号从小到大输出,就让vector反着输出 cout << choose[i] << " "; return 0; } /* 输入数据: 5 8 3 5 1 2 2 4 5 2 1 3 */
先从最大(dp[5][8])倒着往前推,如果dp[5][8]==dp[4][8]则回到dp[4][8]否则回到dp[4][8-2]即dp[4][6]然后同理继续往前推,直到j=0或i=0时结束,j=0时,是没有容量了,i=0时是没有物品了
滚动数组优化:(滚动数组由于1维,无法回溯但优化了空间复杂度)
#include <iostream> #include <vector> #include <algorithm> using namespace std; const int MAXN = 10010; //定义最大物品的数量 const int MAXV = 10010; //定义最大背包的容量 int N; //储存物品数量 int V; //定义背包的容量 int w[MAXN]; // 储存每件物品的重量w[i] int c[MAXV]; //储存每件物品的价值c[i] int better_dp[MAXV]; //一维dp滚动数组(因为只用到第n件物品和第n-1件物品数据,所以可以采取滚动数组优化 void better_knapsack() { //边界处理 for (int i = 0; i <= V; i++) better_dp[i] = 0; //状态更新 for (int i = 1; i <= N; i++) //倒序枚举v(V-0) for (int v = V; v >= w[i]; v--) //必须倒序,防止覆盖会用到的值,v>=w[i]就行,否则better_dp[v]=better_dp[v]没意义 better_dp[v] = max(c[i] + better_dp[v - w[i]], better_dp[v]); //利用滚动数组 } int main() { cin >> N >> V; //输入物品个数和最大的背包容量 for (int i = 1; i <= N; i++) cin >> w[i]; for (int i = 1; i <= N; i++) cin >> c[i]; better_knapsack(); cout << endl << better_dp[V] << endl; //输出最大值 return 0; } /* 输入数据: 5 8 3 5 1 2 2 4 5 2 1 3 */