算法实验4-1:回溯法01背包
#include<bits/stdc++.h>
using namespace std;
int value[100];
int weight[100];
vector<int> track;
int visited[100] = {0};
int panduan(int visited[],int n)//前n-1个物品都没有放进背包的话返回 0
{
int sym = 0;
for (int i = 0; i < n - 1; i++)
{
if(visited[i]!=0)
{
sym = 1;
}
}
return sym;
}
void backtrack( int weight[], int value[], vector<int> track, int maxbag, int n, int max_value,int k,int sum,int sum_value)
{ //初值0100
if(track.size()==n)
{
return;
}
int u = 0;
int sum2 = 0;
int sum2_value = 0;
vector<int> track2;
while(k)
{
u = 0;
sum2 = 0;
sum2_value = 0;
if(visited[k-1] == 0 && k-1 >= 0)
{
sum += weight[k-1];
if (sum <= maxbag)
{
//物品加入背包
track.push_back(k-1);
visited[k - 1] = 1;
sum_value += value[k-1];
cout <<"将"<<k-1<<"号物品放入背包,"<< "当前物品: ";
k++;
if (sum_value > max_value)
{
max_value = sum_value;
}
for (int t = 0; t < track.size(); t++)
{
cout << track[t] << ' ';
}
cout<<"当前最大价值为:" << " " << max_value;
cout << endl << endl;
//搜索树触底,到了最后一层
if (k == n + 1)
{
if(panduan(visited,n)==0)//前n-1个物品都没放进来,仅仅只放进来了最后一个
//(二叉搜索树的倒数第二枝,(倒数第一枝是全零),此时跳出循环)
{
cout <<"*******************************"<<endl<<"最终最大价值" << max_value <<endl<<"*******************************"<<endl;
break;
}
else//否则
{//弹出触底的物品
k -= 2;
if(k>=0)
{
track.pop_back();
sum -= weight[k];
sum_value -= value[k];
visited[k] = 0;
cout << "搜索树触底,弹出一个物品"<<k<<",当前物品编号: ";
for (int t = 0; t < track.size(); t++)
{
cout << track[t]<<' ';
}
cout<<"当前最大价值为:" << " " << max_value;
cout << endl << endl;
//弹出触底元素之前的前一个物品
while(visited[k]==0 && k >= 0)
{
k--;
}
visited[k] = 0;
track.pop_back();
sum -= weight[k];
sum_value -= value[k];
cout << "弹出一个物品"<<k<<",当前物品编号: ";
k += 2;
for (int t = 0; t < track.size(); t++)
{
cout << track[t]<<' ';
}
cout<<"当前最大价值为:" << " " << max_value;
cout << endl << endl;
}
}
}
}
else
{
//不能加入背包
sum -= weight[k - 1];
///
//把不能加入背包的物品后面的物品遍历一次,能加入的计算max但是不做实质性的加入,不能的跳过
u = k;
u++;
sum2 = sum;
sum2_value = sum_value;
track2 = track;
cout << "**********" << endl;
cout << k - 1 << "号物品不能放入背包,假设考虑它后面的物品"<<endl;
/*while(u<=n)
{
sum2 += weight[u - 1];
if(sum2 <= maxbag)
{
sum2_value += value[u - 1];
if(max_value < sum2_value)
{
max_value = sum2_value;
}
cout <<"将"<<u-1<<"号物品放入背包,"<< "当前物品: ";
track2.push_back(u - 1);
for (int t = 0; t < track2.size(); t++)
{
cout << track2[t] << ' ';
}
cout<<"当前最大价值为:" << " " << max_value;
cout << endl << endl;
}
else
{
sum2 -= weight[u - 1];
cout << u - 1 << "号物品不能放入背包"<<endl;
}
u++;
}*/
if(u<=n && u>=1)
{
backtrack(weight, value, track2, maxbag, n, max_value, u, sum2, sum2_value);
}
//弹出背包当下最后一个物品
k--;
if(visited[k-1] != 0&& k-1>=0)
{//前一个物品在背包的话,弹出它
visited[k - 1] = 0;
track.pop_back();
sum -= weight[k - 1];
sum_value -= value[k - 1];
cout << "弹出一个物品"<<k-1<<",当前物品编号: ";
k++;
for (int t = 0; t < track.size(); t++)
{
cout << track[t]<<' ';
}
cout<<"当前最大价值为:" << " " << max_value;
cout << endl << endl;
}
else
{//前一个物品不在背包的话,往上找在背包的最后一个,弹出它
while(visited[k-1]==0 && k-1>=0)
{
k--;
}
if(k-1>=0)
{
visited[k - 1] = 0;
track.pop_back();
sum -= weight[k - 1];
sum_value -= value[k - 1];
cout << "弹出一个物品"<<k-1<<",当前物品编号: ";
k++;
for (int t = 0; t < track.size(); t++)
{
cout << track[t]<<' ';
}
cout<<"当前最大价值为:" << " " << max_value;
cout << endl << endl;
}
}
}
}
}
}
int main()
{
int n;
int maxbag;
cin >> n >> maxbag;
for (int i = 0; i < n; i++){
cin >> value[i];
}
for (int i = 0; i < n; i++){
cin >> weight[i];
}
int max_value = 0;
backtrack(weight, value, track, maxbag, n, max_value, 1, 0, 0);
system("pause");
}



浙公网安备 33010602011771号