题目:
0-1背包问题:给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。请分别用动态规划和回溯法编程求解该问题。
两个测试用例:输入数据分别由文件名为 input1.txt、input2.txt的文本文件提供,文件的第1行有2个正整数n和C,分别表示物品数和背包的容量,第2行有n个正整数,表示物品的价值,第3行有n个正整数,表示物品的重量。请分别计算并给出装入背包中物品的最大价值。
这边我用了文件,大家自己创建个文本并修改下地址即可、
样例2:
50 1000
2 4 10 65 10 1 60 25 4 15 50 10 50 45 60 30 85 55 50 25 30 72 66 40 20 82 48 30 70 38 70 80 35 55 30 32 50 40 20 32 28 50 20 30 32 22 25 22 10 25
1 3 8 65 10 1 70 30 5 20 69 15 80 75 110 58 198 130 120 60 73 180 165 100 50 208 122 77 180 100 192 220 98 160 88 96 155 125 63 101 90 162 66 105 118 82 95 115 56 158
//动态规划
#include<bits/stdc++.h>
using namespace std;
int n, C;
int value[200];
int weight[200];
int OptimalSolution[200]; //最优解;OptimalSolution[i]=1代表物品i放入背包,0代表不放入
int judge[200]; //物品i放入背包,0代表不放入
int Sumvalue = 0;
int Sumweight = 0;
int OptimalValue = 0; //最优价值;当前的最大价值,初始化为0
int main() {
fstream fp;
fp.open("C://Users//Administrator//Desktop//算法//实验5:0-1背包问题//0-1背包问题 input 1.txt", ios::in);
if (!fp.is_open()) {
cout << "打开文件失败!!\n";
return 1; // 返回异常;
}
fp >> n >> C;
for (int i = 0; i < n; i++) {
fp >> value[i];
}
for (int i = 0; i < n; i++) {
fp >> weight[i];
}
//动态规划
int dp[80][1100] = { 0 };
for (int j =weight[0]; j <= C; j++) {
dp[0][j] = value[0];//第一行大于背包容量大于物品质量的放物品0的价值
}
for (int i = 1; i < n; i++) {// 遍历物品 因为第一行已经放过,所以从第二行就是第二个物品开始放
for (int j = 0; j <=C; j++) {// 遍历背包容量
if (j < weight[i]) {
dp[i][j] = dp[i - 1][j];
}
else {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
}
cout << dp[n-1][C]<<endl;
}
//回溯法
#include<bits/stdc++.h>
using namespace std;
int n, C;
int value[200];
int weight[200];
int OptimalSolution[200] = {0}; //最优解;OptimalSolution[i]=1代表物品i放入背包,0代表不放入
int judge[200] = {0}; //物品i放入背包,0代表不放入
double Sumvalue = 0;
int Sumweight = 0;
int OptimalValue = 0; //最优价值;当前的最大价值,初始化为0
bool critize(int t, int Sweight, int Svalue) {
int temp = Svalue;
while (t <= n && C - Sweight >= weight[t]) {
Sweight += weight[t];
temp += value[t];
t++;
}
if (t <= n)temp += value[t] * 1.0 / weight[t] * (C - Sweight);
if (temp > OptimalValue)return true;
else return false;
}
void backtrck(int t, int Sumweight, int Sumvalue) {
if (t > n) {
if (Sumvalue > OptimalValue) {
OptimalValue = Sumvalue;
//cout << "#$%^" << Sumvalue;
for (int i = 1; i <= n; i++) {
OptimalSolution[i] = judge[i];
}
}
}
else {
//遍历当前节点的子节点:0 不放入背包,1放入背包
if (C - Sumweight >= weight[t]) {
Sumweight += weight[t];
Sumvalue += value[t];
judge[t] = 1;//标记已经放入
backtrck(t + 1, Sumweight, Sumvalue);
judge[t] = 0;
Sumweight -= weight[t];
Sumvalue -= value[t];
}
if(Sumweight<=C && critize(t,Sumweight,Sumvalue))backtrck(t + 1, Sumweight, Sumvalue);
}
}
int main() {
fstream fp;
fp.open("C://Users//Administrator//Desktop//算法//实验5:0-1背包问题//0-1背包问题 input 2.txt", ios::in);
if (!fp.is_open()) {
cout << "打开文件失败!!\n";
return 1; // 返回异常;
}
fp >> n >> C;
for (int i = 1; i <= n; i++) {
fp >> value[i];
}
for (int i = 1; i <= n; i++) {
fp >> weight[i];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
double a = (double)value[i] / weight[i];
double b = (double)value[j] / weight[j];
if (a > b) {
swap(weight[i], weight[j]);
swap(value[i], value[j]);
}
}
}
int t = 1;
backtrck(t, Sumweight, Sumvalue);
cout << OptimalValue << endl;
}