最小重量机器设计问题

  一、实验目的

1、了解回溯法和分支限界法的基本思想。

2、运用回溯法和分支限界法解决最小重量机器设计问题。

二、实验要求

最小重量机器设计问题:设某一机器由n个部件组成,每一种部件可以从m个不同的供应商处购得。设wij是从供应商j处购得的部件i的重量,cij是相应的价格。试设计一个算法,给出总价格不超过c的最小重量机器设计。分别用回溯法和分支限界法实现问题的算法。

三、算法思想和实现

1、回溯法

(1)此问题是一棵排列树,设开始时bestx=[-1,-1,……,-1]则相应的排列树由x[0:n-1]的所有排列构成。

(2)找最小重量机器设计的回溯算法Backtrack是类machine的公有成员。私有数据成员整型数组Savex保存搜索过的路径,到达叶节点后将数据赋值给数组bestx。成员bestw记录当前最小重量,cc表示当前花费,cw表示当前的重量。

(3)在递归函数Backtrack中,在保证总花费不超过c的情况下:

当i=n时,当前扩展结点是排列树的叶节点。此时搜索到一个解,判断此时的最小重量是否小于当前最小重量,若小于则更新bestw,并得到搜索路径bestx。

  当i< P>

#include

using namespace std;

#define N 3

#define M 3

int w[N][M]={{1,2,3},{3,2,1},{2,2,2}};

int c[N][M]={{1,2,3},{3,2,1},{2,2,2}};

class machine

{public:

       void InitMachine(int C);

       void Backtrack(int i);

       void printsave();

private:

       int COST;//题目中的C

       int cw;//当前的重量

       int cc;//当前花费

       int bestw;//当前最小重量

       int bestx[N];//最优解

       int savex[N];//savex[i]如果为j,表示第i个零件应该选用第j个人供应的

};

void machine::InitMachine(int C){  

   COST=C;

   cw=cc;

   bestw=-1;//初值为-1,标记最小重量是否变化

   for(int j=0;j< P>

      bestx[j]=-1;

}

void machine::Backtrack(int i)

{    if(i>=N)//达到叶子节点

     {if(cw<以前最小重量><>

     {

        bestw=cw;

        cout<<“************************************”<< P>

        cout<<“搜索路径的bestw:”<<

        for(int k=0;k<>

        {

            cout<<<“”;< P>

            savex[k]=bestx[k];

         }

          cout<< P>

       }

       return;

     }

      for(int j=0;j<>

      {

       if((cc+c[i][j]0))

        {cc+=c[i][j];

         cw+=w[i][j];

         bestx[i]=j;

         Backtrack(i+1);

         bestx[i]=-1;

         cc-c[i][j];

         cw-=w[i][j];

         }

       }

void machine::printsave(){

   if(bestw==-1) {     cout<<“输入的总价格太小!”<< P>

    }

   else {

    cout<<“************************”<< P>

    cout<<“最优重量(bestw )是:”<<

    for(int k=0;k< P>

    cout<<“第”<<<“个部件由第”<<<“供应商供应”<< P>

    cout<< P>

   }

}

int main(){ 

mach Mach;

   int C;

   cout<<“输入总价格不超过的C:”;

   cin>>C;//输入最小花费

   Mach.InitMachine(C);

   Mach.Backtrack(0);

   Mach.printsave();

   return 0;

}

2、分支限界法

解空间为一棵排列树,采用优先队列式分支限界法找出所给的最小重量机器设计,开始时,将排列树的根节点置为当前扩展结点。在初始扩展结点处还设有选定部件是哪个供应商提供的,故cv=0,cw=0,position=0,peer=0,1≤i≤n。x[1:n]记录供应商的选择while完成对排列树内部结点的有序扩展。循环体内依次从活结点优先队列中取出具有最小重量的结点,依次为当前扩展结点。并且花费不超过c并加以扩展,队列为空时则结束循环。当peer=n时,此时扩展结点是叶节点,得到当前的最小重量和最优解数组x。若peer< P>

  #include “fstream.h”  

  #include “iostream.h”  

   struct nodetype   {  

      int peer;  

      struct nodetype *parent;  

      int position;  

      double cw;  

      double cv;  

      double r;    };  

   struct nodetype *queues[100000000];  

   /////////////////////////////////小根堆///////////////////////////////  

   void insert(struct nodetype *x, int oldlast) //x是要插入的数

 { //oldlast是目前堆的元素数目                                               

       int last = oldlast+1;

       queues[last]=x;

       int i=last;                                                      

   while((i > 1)&&(queues[i]->r < queues[i/2]->r)) {

 struct nodetype *temp;

             temp=queues[i];  

             queues[i]=queues[i/2];

             queues[i/2]=temp;

             i = i/2;

}

   }     //last是当前堆的元素个数,执行该函数后                                                             

   struct nodetype * deletemin(int last,struct nodetype *a[])

  {      //返回堆的第一个元素(即最小元素)    

 struct nodetype *temp;

        temp=a[1];

        a[1]=a[last];

last –;                                                       

        int i = 1;  

int j=0;                                                       

        while(i <= last/2)                                              

{      if((a[2*i]->r < a[2*i+1]->r)||(2*i == last)) j = 2*i;

          elsej=2*i+1;                                                      if(a[i]->r > a[j]->r) {                     

            struct nodetype *temp;  

            temp=a[i];  

            a[i]=a[j];  

            a[j]=temp;

            i = j;                                                 

          }                                                          

           else return(temp);                                         

       }                                                              

       return(temp);                                                  

   }                                                                     

  void main()  /////////////////////////////////小根堆///////////////////////////////  

   {  

       ifstream fin(“input.txt”);  

       ofstream fout(“output.txt”);  

       int n,m,c;  

       fin>>n;fin>>m;fin>>c;  

       double **w=new  double*[n+1];  

       double **cc=new double*[n+1];  

       for(int i=1;i<=n;i++){  

          w[i]=new double[m+1];  

          cc[i]=new double[m+1];  

      }  

       for(i=1;i<=n;i++)  

           for(int j=1;j<=m;j++)  

            fin>>cc[i][j];  

       for(i=1;i<=n;i++)  

            for(int j=1;j<=m;j++)  

            fin>>w[i][j];  

        double *cmin=new double[n+1];  

        double *wmin=new double[n+1];  

        for(i=1;i<=n;i++)   {  

        cmin[i]=cc[i][1];  

        wmin[i]=w[i][1];  

        for(int j=2;j<=m;j++)     {  

        if(cmin[i]>cc[i][j]) cmin[i]=cc[i][j];  

        if(wmin[i]>w[i][j]) wmin[i]=w[i][j];  

     }  

    }  

    double *rc=new double[n+1];//剩余部件最小价格和  

    double *rw=new double[n+1];//剩余部件最小重量和  

    rc[n]=0;rw[n]=0;  

    for(i=n-1;i>=1;i–)     {  

   rc[i]=rc[i+1]+cmin[i+1];  

      rw[i]=rw[i+1]+wmin[i+1];  

  }  

    struct nodetype *node=new struct nodetype;  

    node->peer=0;  

    node->cv=0;  

    node->cw=0;  

    node->position=0;  

    node->r=rw[1]+wmin[1];  

    insert(node,0);  

    int cpeer=0;  

    int q_len=1;  

    bool isend=false;  

    while(!isend&&q_len>0)  

    {   node=deletemin(q_len,queues);  

        q_len–;  

        if(node->peer==n)    {  

               isend=true;  

               fout<cw<< *x=”new” int>

                        for(int k=n;k>=1;k–)  {  

                 x[k]=node->position;  

                 node=node->parent;  

               }  

              for(k=1;k<=n;k++)   fout<<<” P < ?;  >

           return;}

}

四、结果

input.txt

3 3 4

1 2 3

3 2 1

2 2 2

1 2 3

3 2 1

2 2 2

output.txt

4

1 3 1

五、总结

分支限界法与回溯法对当前扩展结点所采用的扩展方式不同。在分支限界法中,每一个结点只有一次机会成为扩展结点。而在回溯法中,每一个活结点有多次机会成为扩展结点。

 

 

如果您喜欢这篇文章请点击右上角按钮, 即可分享到《朋友圈》或许 你小小的一个分享动作就可以照亮无数人的命运。

欢迎关注公众微信:yingchunhua365

扫描以下二维码


《最小重量机器设计问题》

    传递正能量,分享励志故事,

    从这里起航……

    请把正能量传递下去, 

    帮助和影响更多的人,

 

 

 

    原文作者:分支限界法
    原文地址: https://blog.csdn.net/yingchunhua365/article/details/17470835
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞