裝載問題(最優裝載問題變形)-回溯法-深度搜索


問題描述:

有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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM