背包有关问题(DP、回溯)

详细页面:http://www.verydemo.com/demo_c92_i63400.html

背包问题(DP、回溯)

 

算法设计例题:背包问题(DP、回溯)

memory limit: 65536KB    time limit: 500MS

accept: 7    submit: 24

Description

 

Input

 

Output

 

Sample Input

 
 
 
 
 
 

Sample Output

 
 

 

 

#include"iostream"

#include"algorithm"
#include"map"
using namespace std ;
class Knapsack{
public :
    double c ;//Knapsack capacity
    int n ; // item numbers
    double w [1000] ;// Item weight array
    double p [1000] ;//item value array
    double  cw ;//current weight
    double cp ;// current value
    double bestp; // current best value
    double setdata ( )
    {
        cw = 0.0 ;
        cp = 0.0;
        bestp =0 ;
    }
    void backtrack(int i)
    {
        if ( i > n )
        {

             bestp = cp ;
            //  为什么不用和前一个进行比较就进行跟新呢?者主要得利域贪心算法的好处,。进入左子树时不需要计算上界,因为其上界以其父结点的上界相同
            return  ;//to Leaf node
        }
        //sort child tree
        if ( cw + w [i] <= c )
        {
            //into left child tree
            cw += w[i];
            cp+=p[i];
            backtrack( i + 1 );
            cw -= w [ i ] ;
            cp -= p[i] ;
        }
        if(bound( i+1 ) > bestp )
            backtrack( i + 1 ) ; //into light child tree
    }
    //calculate up bound
     double bound( int i )
    {
        //calculate up bound
        double cleft = c - cw ;//residual capacity
        double bound = cp ;
        //With items unit weight value decreasing order load items
        while ( i <= n && w[i] <= cleft )
        {
            cleft -= w[i];
            bound += p[i];
            i++;
        }
        //Backpack  being filled with
       if ( i <= n )
        {
            bound += p[i] / w[i]* cleft  ;
        }
        return bound ;
    }

};
int main()
{
    Knapsack kk ,kk_1 ;
    multimap< double ,int > m ;
    multimap<double ,int >::reverse_iterator t;
    int n;
    int T ;
    int j=1 ;
    cin>>T;
    while(T>0)
    {
        cin>>kk.n;
        cin>>kk.c;
        int i =1 ;
        while(i<=kk.n)
        {
            cin>>kk.w[i];
            cin>>kk.p[i];
            m.insert(pair<double,int >(kk.p[i]/kk.w[i],i));
            i++;
        }
        //sort the data
        n=kk.n;
        i =  1 ;
        t = m.rbegin();
        while(t!=m.rend())
        {
            kk_1.w[i] = kk.w[t->second];
            kk_1.p[i] = kk.p[t->second];
          //  cout<<":"<<kk_1.w[i]<<" "<<kk_1.p[i];
            i++;
            ++t;
        }
        m.clear();
        kk_1.c = kk.c ;
        kk_1.n = kk.n;
        kk_1.setdata();
        kk_1.backtrack(1);
        int b =kk_1.bestp;
        cout<<b<<endl;
        T--;
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯法解0_1背包问题时,会用到状态空间树。在搜索状态空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。当右子树有可能包含最优解时才进入右子树搜索,否则将右子树剪去。设r是当前剩余物品价值总和;cp是当前价值;bestp是当前最优价值。当cp+r≤bestp时,可剪去右子树。计算右子树中解的上界可以用的方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。由此得到的价值是右子树中解的上界,用此值来剪枝。 为了便于计算上界,可先将物品依其单位重量价值从大到小排序,此后只要顺序考察各物品即可。在实现时,由MaxBoundary函数计算当前结点处的上界。它是类Knap的私有成员。Knap的其他成员记录了解空间树种的节点信息,以减少函数参数的传递以及递归调用时所需要的栈空间。在解空间树的当前扩展结点处,仅当要进入右子树时才计算上界函数MaxBoundary,以判断是否可以将右子树减去。进入左子树时不需要计算上界,因为其上界与父结点的上界相同。 在调用函数Knapsack之前,需要先将各物品依其单位重量价值从达到小排序。为此目的,我们定义了类Objiect。其中,运算符与通常的定义相反,其目的是为了方便调用已有的排序算法。在通常情况下,排序算法将待排序元素从小到大排序。 在搜索状态空间树时,由函数Backtrack控制。在函数中是利用递归调用的方法实现了空间树的搜索
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值