背包问题
1.01背包问题
https://blog.csdn.net/xp731574722/article/details/70766804
https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html
/*01背包问题*/ #include<iostream> #include<vector> #include<algorithm> using namespace std; //找不超过容量的最大价值 void Findmax(vector<int>&v, vector<int>&c, int C, vector<vector<int>>&dp){ for (int i = 1; i <v.size(); i++){ for (int j = 1; j <=C; j++){ if (c[i] > j){ dp[i][j] = dp[i - 1][j];//如果第i件物品所占容量大于当前背包容量,则不放入 } else{ dp[i][j] = max(dp[i - 1][j],dp[i-1][j-c[i]]+v[i]);//选择不放入第i个,和放入第i个后价值最大的 } } } } //找选择的物品的序号 void Findpos(int i, int j, vector<int>&v, vector<int>&c, vector<int>&item, vector<vector<int>>&dp) { if (i > 0) { //cout << dp[i][j] << endl; //cout << dp[i - 1][j - c[i]] + v[i]; if (dp[i][j] == dp[i - 1][j])//相等说明没装第i件商品 { item[i] = 0;//全局变量,标记未被选中 Findpos(i - 1, j,v,c,item,dp); } else if (j - c[i] >= 0 && dp[i][j] == dp[i - 1][j - c[i]] + v[i]) { item[i] = 1;//标记已被选中 //cout << i << endl; //cout << j << endl; Findpos(i - 1, j - c[i],v,c,item,dp);//回到装包之前的位置 } } } int main(){ vector<int>v = { 0, 60, 100, 120 };//每件物品对应价值 vector<int>c = { 0, 1, 2, 3 };//每件物品所占容量,第一个零是为了方面从序号1开始所以补的 int C = 5; vector<vector<int>>res(v.size(), vector<int>(C+1, 0));//res[i][j]代表前i件物品恰放入容量j(还能装j的容量)的背包的最大价值 Findmax(v, c, C,res); //填表 for (int i = 0; i < res.size(); i++){ for (int j = 0; j < res[0].size(); j++){ cout << res[i][j] << " "; } cout << endl; } cout << res[v.size()-1][C] << endl;//最大价值 vector<int>item(v.size(), 0); Findpos(v.size() - 1, C, v, c, item, res); for (int i = 0; i < item.size(); i++){ if (item[i] != 0){ cout << i<< endl; } } system("pause"); return 0; }
2.完全背包问题
https://blog.csdn.net/na_beginning/article/details/62884939
/*完全背包问题*/ #include<iostream> #include<vector> #include<algorithm> using namespace std; //找不超过容量的最大价值 void Findmax(vector<int>&v, vector<int>&c, int C, vector<vector<int>>&dp){ for (int i = 1; i <v.size(); i++){ for (int j = 1; j <=C; j++){ if (c[i] > j){ dp[i][j] = dp[i - 1][j];//如果第i件物品所占容量大于当前背包容量,则不放入 } else{ dp[i][j] = max(dp[i - 1][j],dp[i][j-c[i]]+v[i]);//此处与01背包区别 } } } } //找选择的物品的序号 void Findpos(int i, int j, vector<int>&v, vector<int>&c, vector<int>&item, vector<vector<int>>&dp) { if (i > 0) { //cout << dp[i][j] << endl; //cout << dp[i - 1][j - c[i]] + v[i]; if (dp[i][j] == dp[i - 1][j])//相等说明没装第i件商品 { item[i] = 0;//全局变量,标记未被选中 Findpos(i - 1, j,v,c,item,dp); } else if (j - c[i] >= 0 && dp[i][j] == dp[i - 1][j - c[i]] + v[i]) { item[i] = 1;//标记已被选中 //cout << i << endl; //cout << j << endl; Findpos(i - 1, j - c[i],v,c,item,dp);//回到装包之前的位置 } } } int main(){ vector<int>v = { 0, 1, 3, 5,9 };//每件物品对应价值 vector<int>c = { 0, 2, 3, 4,7 };//每件物品所占容量,第一个零是为了方面从序号1开始所以补的 int C = 10; vector<vector<int>>res(v.size(), vector<int>(C+1, 0));//res[i][j]代表前i件物品恰放入容量j(还能装j的容量)的背包的最大价值 Findmax(v, c, C,res); //填表 for (int i = 0; i < res.size(); i++){ for (int j = 0; j < res[0].size(); j++){ cout << res[i][j] << " "; } cout << endl; } cout << res[v.size()-1][C] << endl;//最大价值 vector<int>item(v.size(), 0); Findpos(v.size() - 1, C, v, c, item, res); for (int i = 0; i < item.size(); i++){ if (item[i] != 0){ cout << i<< endl; } } system("pause"); return 0; }