zoukankan      html  css  js  c++  java
  • 装载问题(最优装载问题变形)-回溯法-深度搜索

    问题描述:

    有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;
    }
  • 相关阅读:
    2017(秋)软工作业: (2)硬币游戏—— 代码分析与改进
    软工作业(1)课程学习热身
    用户体验分析:以 “师路南通网站” 为例
    用户体验分析: 以 “南通大学教务管理系统微信公众号” 为例
    软件工程第二次作业:硬币游戏—— 代码分析与改进
    自我介绍
    用户体验分析---以师路南通为例
    用户体验分析---七八点照相馆
    硬币游戏—— 代码分析与改进
    About me
  • 原文地址:https://www.cnblogs.com/lvjingyuan/p/14070700.html
Copyright © 2011-2022 走看看