回溯法_0/1背包问题(非递归)

这个代码并不好!我写这个主要是理清思路。如果要具体明白算法,可以参考《算法设计与分析》181页和《计算机算法设计与分析》138页,

#include <stdio.h>
#include <stdlib.h>
#define n 5
#define M 50
typedef struct 
{
float w;
float p;
float v;
}OBJECT;
OBJECT ob[n];
//int x[n];
//int y[n]={0,0,0,0,0};
int PP[n]={-1,-1,-1,-1,-1};
float p_est;
float p_total;
float w_cur;
float p_cur;
void sort_v(OBJECT* ob)
{
   float t_v;
   float t_w;
   float t_p;
   for(int i=0;i<n;i++)
   {
  for(int j=i+1;j<n;j++)
  {
          if(ob[i].v<ob[j].v)
 {
             t_v=ob[i].v;
ob[i].v=ob[j].v;
ob[j].v=t_v;
t_w=ob[i].w;
ob[i].w=ob[j].w;
ob[j].w=t_w;
t_p=ob[i].p;
ob[i].p=ob[j].p;
ob[j].p=t_p;
 }
  }
   }
   for(int t=0; t<n;t++)
   {
       printf(“%f\n”,ob[t].v);
   }
}
void main()
{
    //初始化
    float w[n]={5,15,25,27,30};
float p[n]={12,30,44,46,50};
for(int l=0;l<n;l++)
{
ob[l].w=w[l];
ob[l].p=p[l];
ob[l].v=p[l]/w[l];
}
//排序
sort_v(ob);
int k=0;
p_total=0;
    w_cur=0;
    p_cur=0;
p_est=0;
    while(k>=0)
{
         while(1)
{
if(k==n)
{
                if(p_cur>p_total)
{
p_total=p_cur;
                    for(int v=0;v<n;v++)
{
                       printf(“%d\t”,PP[v]);
}
printf(“%f\n”,p_total);
}
k++;

}
if(w_cur+ob[k].w<=M&& k<n)
{
                w_cur=w_cur+ob[k].w;
p_cur=p_cur+ob[k].p;
                PP[k]=1;
k++;
break;
}
else
{
                if(w_cur+ob[k].w>M && k<n)
{
p_est=p_cur+(M-w_cur)*ob[k].v;
PP[k]=0;
k++;
break;
}
}
    break;
}
//回溯——开始
while(k>n)
{
for(int l=n-1;PP[l]!=1;l–)
{
PP[l]=-1;
}
                        PP[l]=0;
if(l==0) exit(0);
p_cur=p_cur-ob[l].p;
w_cur=w_cur-ob[l].w;
                        k=l+1;
}
       
}
}
  
下面是《算法设计与分析》的代码:::

#define M   ……  //自己定义

#define n   ……

typedef struct 
{
float w;                      //重量
float p;                      //价值
float v;                      //价值重量比
}OBJECT;
OBJECT ob[n];
int x[n];                            //可能的解向量
int y[n];                            //当前搜索的解                                                                       //别忘了开辟空间  malloc(), new.
float p_est;                    //最大价值量的估计
float p_total;                   //上界
float w_cur;                    //总重量 
float p_cur;                    //总价值

float knapsack_back( OBJECT ob[],float M,int n,BOOL x[])

{

    int i,k;

    float  w_cur,p_total,p_cur,w_est,p_est;

    BOOL *y=new BOOL[n];

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

   {

    ob[i]].v=ob[i].p/ob[i].w;

    y[i]=FALSE;

   }

   merge_sort(ob,n);

   k=0;

   while (k>=0)

   {

        w_est=w_cur;

        p_est=p_cur;

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

       {

        w_est=w_est+ob[i].w;

        if(w_est<M)

            p_est=p_est+ob[ i].p;

         else 

         {

            p_est=p_est+((M-w_est+ob[i].w)/ob[i].w)*ob[i].p;

            break;

         }

      }

         if(p_est>p_total)

          {

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

               {

                   if(w_cur+ob[i].w<=M)

                     {

                        w_cur=w_cur+ob[i].w;

                       p_cur=p_cur+ob[i].p;

                       y[i]=TRUE;

                     }

                     else

                     {

                        y[i]=FALSE;

                          break;

                     }

               }

                if(i>=n)

                 {

                     if(p_cur>p_total)

                      {

                           p_total=p_cur;

                             k=n;

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

                             x[i]=y[i];

                       }

                  }

                 else  k=i+1;

          }   

         else

           {

               while((i>=0)&&(!y[i]))

                                i=i-1;

                           if(i<0)     break;

                            else

                             {

                                 w_cur=w_cur-ob[i].w;

                                 p_cur=p_cur-ob[i].p;

                                y[i]=FALSE;

                                 k=i+1;

                              }

           }

    }

     delete y;

     return  p_total;

   }

还有一个比较典型的代码::::

 参考迭代回溯::http://blog.csdn.net/liufeng_king/article/details/8762073

  1. #include “stdafx.h”  
  2. #include <iostream>  
  3. using namespace std;   
  4.   
  5. template<class Type>  
  6. Type MaxLoading(Type w[ ], Type c, int n, int bestx[ ]);  
  7.   
  8. int main()  
  9. {     
  10.     int n=3,m;  
  11.     int c=50,c2=50;  
  12.     int w[4]={0,10,40,40};  
  13.     int bestx[4];  
  14.   
  15.     m=MaxLoading(w, c, n, bestx);  
  16.   
  17.     cout<<“轮船的载重量分别为:”<<endl;  
  18.     cout<<“c(1)=”<<c<<“,c(2)=”<<c2<<endl;  
  19.   
  20.     cout<<“待装集装箱重量分别为:”<<endl;  
  21.     cout<<“w(i)=”;  
  22.     for (int i=1;i<=n;i++)  
  23.     {  
  24.         cout<<w[i]<<” “;  
  25.     }  
  26.     cout<<endl;  
  27.   
  28.     cout<<“回溯选择结果为:”<<endl;  
  29.     cout<<“m(1)=”<<m<<endl;  
  30.     cout<<“x(i)=”;  
  31.   
  32.     for (int i=1;i<=n;i++)  
  33.     {  
  34.         cout<<bestx[i]<<” “;  
  35.     }  
  36.     cout<<endl;  
  37.   
  38.     int m2=0;  
  39.     for (int j=1;j<=n;j++)  
  40.     {  
  41.         m2=m2+w[j]*(1-bestx[j]);  
  42.     }  
  43.     cout<<“m(2)=”<<m2<<endl;  
  44.   
  45.     if(m2>c2)   
  46.     {  
  47.         cout<<“因为m(2)大于c(2),所以原问题无解!”<<endl;  
  48.     }  
  49.     return 0;  
  50. }  
  51.   
  52.   
  53. template <class Type>  
  54. Type MaxLoading(Type w[],Type c,int n,int bestx[])//迭代回溯法,返回最优载重量及其相应解,初始化根结点  
  55. {  
  56.     int i=1;//当前层,x[1:i-1]为当前路径  
  57.     int *x=new int[n+1];  
  58.   
  59.     Type bestw=0,      //当前最优载重量  
  60.          cw=0,         //当前载重量  
  61.          r=0;          //剩余集装箱重量  
  62.   
  63.     for (int j=1;j<=n;j++)  
  64.     {  
  65.         r+=w[j];  
  66.     }  
  67.   
  68.     while(true)//搜索子树  
  69.     {       
  70.         while(i<=n &&cw+w[i]<=c)//进入左子树  
  71.         {  
  72.             r-=w[i];  
  73.             cw+=w[i];  
  74.             x[i]=1;  
  75.             i++;  
  76.         }  
  77.           
  78.         if (i>n)//到达叶结点  
  79.         {        
  80.             for (int j=1;j<=n;j++)  
  81.             {  
  82.                 bestx[j]=x[j];  
  83.             }  
  84.             bestw=cw;  
  85.         }  
  86.         else//进入右子树  
  87.         {            
  88.             r-=w[i];  
  89.             x[i]=0; i++;  
  90.         }  
  91.         while (cw+r<=bestw)  
  92.         { //剪枝回溯  
  93.             i–;     
  94.             while (i>0 && !x[i])  
  95.             {   
  96.                 r+=w[i];  
  97.                 i–;  
  98.             }     
  99.             //从右子树返回  
  100.             if (i==0)  
  101.             {  
  102.                 delete []x;  
  103.                 return bestw;  
  104.             }  
  105.             x[i]=0;  
  106.             cw-=w[i];  
  107.             i++;  
  108.         }   
  109.     }    
  110. }  

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