算法实验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");
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

posted @ 2023-04-06 08:15  在天边偷看小天使  阅读(9)  评论(0)    收藏  举报  来源