装载问题(最优装载问题变形)-回溯法-深度搜索

问题描述:

有n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为wi,且∑wi <= c1 + c2。

问是否有一个合理的装载方案,可将这n个集装箱装上这2艘轮船。如果有,找出一种装载方案。

问题分析:

如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。
(1)首先将第一艘轮船尽可能装满;
(2)将剩余的集装箱装上第二艘轮船。

将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近c1。由此可知,装载问题等价于以下特殊的0-1背包问题:

 max∑ wi * xi && ∑ wi * xi <= c1, xi ∈ {0, 1}, 1 <= i <= n;

输入样例:

10  10 
4
7 4 3 5

输出样例:

放入第一艘轮船的集装箱: 1  3
放入第二艘轮船的集装箱: 2  4
BestWeight =  10

代码: 

1.递归回溯

#include <bits/stdc++.h>
using namespace std;

int capacity1,capacity2;  //轮船1,2的载重量 
int n;                    //n个集装箱 
int weight[1000]={0};     // n个集装箱的重量, weight【i】表示第i个集装箱的重量
int PreWeight = 0;        // 深度搜索时,当前载重 
int RestWeight = 0;       // 深度搜索时,剩余重量 ,注意是未搜索结点的重量 
int BestWeight = 0;       // 记录最大载重,初始为一个很小的数 
bool record[1000]={0};       // 记录当前方案有哪些集装箱被放进第一艘轮船 ,record【i】= 1 表示第i个集装箱被放进去了 
bool BestRecord[1000]={0};   
int k=1;
 
// 剪枝函数   PreWeight + weight[dep] <= capacity1 

//上界函数    RestWeight + PreWeight > BestWeight
 
 
void GetBestRecord()   // 第一艘轮船最多载重的那个方案,有哪些集装箱被放进第一艘轮船 (也叫构造最优解) 
{
    for(int i=1;i<=n;i++)
    {
        BestRecord[i]=record[i];
    }
    return ;
}
 
 
 
void BackTrace(int dep)
{
   if(dep>n)  //搜索到叶子节点,  
   {
      if( PreWeight > BestWeight )   
      {
          BestWeight = PreWeight;   // 记录最优解 
           GetBestRecord();           //  保存路径 
      } 
      return;
   }
   
 
   RestWeight = RestWeight - weight[dep];  // 想想为什么要放这里:搜索到该结点,不管它放不放进第一艘轮船,RestWeight都得减 
  
  
   // 第 dep 个集装箱装入第一艘船 
   if( PreWeight + weight[dep] <= capacity1 )   //能装的下不 
   {
   record[dep] = 1;
   PreWeight = PreWeight + weight[dep];
   if( RestWeight + PreWeight > BestWeight )  BackTrace(dep+1);
   record[dep] = 0;
   PreWeight = PreWeight - weight[dep];
   RestWeight = RestWeight + weight[dep]; 
   }
   
   
   // 第 dep 个集装箱不装入第一艘轮船
   if( RestWeight + PreWeight > BestWeight ) BackTrace(dep+1);    
   
   
   RestWeight = RestWeight + weight[dep] ; 
   return;
}


int main()
{
    // 输入 
    cin>>capacity1>>capacity2;
    cin>>n; 
    for(int i=1;i<=n;i++)
    {
        cin>>weight[i];
        RestWeight = RestWeight + weight[i] ;   //获得总重量 
    }
    
    //搜索 
    BackTrace(1);    
    
    //输出 
    cout<<"第一艘轮船的集装箱:";
    for(int i=1;i<=n;i++)
    {
        if(BestRecord[i]) cout<<i<<" ";
    }
    cout<<endl;
    
    cout<<"第二艘轮船的集装箱:";
    for(int i=1;i<=n;i++)
    {
        if(!BestRecord[i]) cout<<i<<" ";
    }
    cout<<endl;
    
    cout<<"BestWeight="<<BestWeight<<endl;
    
    return 0;
}
原文地址:https://www.cnblogs.com/lvjingyuan/p/14070700.html