回溯法求解01背包问题

解决01背包问题的方法有:动态规划法,回溯法,分治界限法 

知识储备:01背包问题与背包问题的区别;回溯法的基本思想;最优值与最优解的含义

参考书籍:王晓东《算法设计与分析》

//回溯法求解01背包问题
#include<iostream>  

using namespace std;  
  
class Knap  
{  
public:  
    Knap(double *pp,double *ww,double cc,int nn)//构造函数  
    {  
        p=pp;  
        w=ww;  
        c=cc;  
        n=nn;  
        cw=0;  //当前的重量
        cp=0;  //当前的价值
        bestp=0;  //当前价值的最优值
        x=new int[n];  //用于存储第i个物品是否放入,1表示放入,0表示不放入
        bestx=new int[n];  //用于存储最优解
    }  
    double knapsack();//找最优值的函数。  
    double Bound(int i);//边界函数  
    void BackTrack(int i);//回溯函数  
    void output()//输出最优解  
    {  
        cout<<"最优解为:"<<endl;
for(int i=0;i<n;i++)  
            cout<<bestx[i]<<" ";  
        cout<<endl;  
    }  
private:  
    double c;  
    int n;  
    double *w;  
    double *p;  
    double cw;  
    double cp;  
    double bestp;  
    int *x;  
    int *bestx;  
  
};  
 // 回溯函数,实现用回溯法查找最优解
void Knap::BackTrack(int i)  
{  
    if(i>=n)  
    {  
        if(cp>bestp)//保存此时的最优解与最有值,这样下面的bestx就是最优的路径
        {  
            bestp=cp;  
            for(int i=0;i<n;i++)  
                bestx[i]=x[i];  
        }  
        return;  
    }  
    if(cw+w[i]<=c)//left  
    {  
        x[i]=1;//记录进入坐子树  
        cw+=w[i];  
        cp+=p[i];  
        BackTrack(i+1);  
        cw-=w[i]; //完成上面的递归,返回到上一个结点,物品i不放入背包,准备搜索右子树 
        cp-=p[i];  
    }  
   
     x[i]=0;//记录进入右子树  
     BackTrack(i+1);  
   
}  


double Knap::knapsack()  
{  
    //分支判断,如果背包容量足够大,就不用再回溯搜索了 
    int i;  
    double W=0;  
    double P=0;  
    for(i=0;i<n;i++)  
    {  
        W+=w[i];  
        P+=p[i];  
    }  
    if(W<=c)  
        return P;  
//如果背包容量不够大,则有最有的方案,使用回溯方法
    BackTrack(0); 
cout<<"最优值为:";
    return bestp;  
}  
  
  
int main()  
{  
    int n=4; 
cout<<"物品的个数为"<<n<<endl;
cout<<endl;
    double c=10;//背包容量
cout<<"背包的容量为"<<c<<endl;
//p,w分别存在物品的价格与重量,两者是一一对应的关系
    double p[]={42,12,40,25};//物品价值  
    double w[]={7,3,4,5};//物品重量  
    cout<<endl; 
cout<<"物品的价值依次为:"<<endl;
    for(int i=0;i<sizeof(p)/sizeof(double);i++)
{
cout<<"第"<<i+1<<"个物品的价值为"<<p[i]<<endl;
}
cout<<endl;
cout<<"物品的重量依次为"<<endl;
for(i=0;i<sizeof(w)/sizeof(double);i++)
{
cout<<"第"<<i+1<<"个物品的价值为"<<w[i]<<endl;
}
cout<<endl;
    Knap k=Knap(p,w,c,n);  
    cout<<k.knapsack()<<endl;  
   //输出最优解
k.output();  
    return 1;  
}  

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值