01背包问题 及c++ 代码实现

    今天在看july的博客之时,看到其中一道题目的原理为01背包问题,就自己温习了下,写下今天的学习体会。

本文理论分析参考博客:http://www.cnblogs.com/qinyg/archive/2012/04/26/2471829.html

问题描述:   

   

    给定N个物品和一个背包,其中物品i的重量是Wi,其价值为Vi ,背包的容量为C。问应该如何选择装入背包的物品,使得转入背包的物品的总价值为最大?

   (关于01背包问题的其他变种请参看

http://zh.wikipedia.org/wiki/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98

http://love-oriented.com/pack/

    )

     对于此类01背包问题,我们可以使用动态规划分析解决:

    问题分析:

    在选择物品的时候,对每种物品i只有两种选择,即装入背包或不装入背包。不能讲物品i装入多次,也不能只装入物品的一部分。因此,该问题被称为0-1背包问题。

    令V(i,j)表示在前i(1<=i<=n)个物品中能够装入容量为就j(1<=j<=C)的背包中的物品的最大价值,则可以得到如下的动态规划函数:

(1)   V(i,0)=V(0,j)=0 

(2)   V(i,j)=V(i-1,j)  ji  

(3)      V(i,j)=max{V(i-1,j) ,V(i-1,j-wi)+vi) } j>wi

(2)表明:如果第i个物品的重量大于背包的容量,则装人前i个物品得到的最大价值和装入前i-1个物品得到的最大价是相同的,即物品i不能装入背包;

(3)表明:如果第i个物品的重量小于背包的容量,则会有一下两种情况:(a)如果把第i个物品装入背包,则背包物品的价值等于第i-1个物品装入容量位j-wi 的背包中的价值加上第i个物品的价值vi;(b)如果第i个物品没有装入背包,则背包中物品价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。显然,取二者中价值最大的作为把前i个物品装入容量为j的背包中的最优解。

(注:一开始大家对第三个式子比较难以理解,我们可以从这么几点帮助理解:

1.这前i个中,并不是所有的i都被选择了,请大家看下面的代码会更加加深理解。

2.动态规划的概念,有最有子结构,重复子问题。V(i,j)其实是有记录作用的。

我们来看下代码实现:

#include
#include

using namespace std;

int maxNum(int a,int b)
{
    return (a>b)?a:b;
}

void insight(int *exist,int **val,int *w,int bagnum,int weight)
{
    for(int i=bagnum;i>0;i--)
    {   
        if(val[i][weight]>val[i-1][weight])
        {   
            exist[i]=1;
            weight=weight-w[i];
        }   
    }   
    
    for(int j=1;j<=bagnum;j++)
        cout<>bagnum;
    cout<<"please input the limit weight of bag:"<>weight;

    int **val=new int *[bagnum+1];                 //这样定义二维数组,是为了方便传入
    val[0]=new int [(bagnum+1)*(weight+1)];
    for(i=1;i<=bagnum;i++)
        val[i]=val[i-1]+weight+1;

    cout<<"please input the weight of every bag:"<>w[i];
    //cout<<"w=";
    //for(i=0;i<=bagnum;i++)
    //    cout<>v[i];
    //cout<<"v=";
    //for(i=0;i<=bagnum;i++)
    //    cout<

看完此处之后,我们在来看下july大神写的关于


请看http://blog.csdn.net/v_july_v/article/details/6419466

第二节、寻找和为定值的多个数
第21题(数组)
2010年中兴面试题
编程求解:
输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来

并附上我的代码,较原文给出的会更加容易理解一点

#include
#include
using namespace std;

list lis;                 
 //这边我们将list用作了栈,当然也可以用stack容器,不过stack其实是一种容器适配器,其默认实现方式是用list实现的
void findNSum(int sum,int n)
{
    if(sum<=0||n<=0)             //递归退出条件
        return;
    if(sum==n)                   //打印条件
    {   
        for(list::iterator iter=lis.begin();iter!=lis.end();iter++)
            cout<<*iter<<"+";
        cout<>sum;
    cout<<"please input the n:"<>n;
    findNSum(sum,n); 
    return 0;
}




你可能感兴趣的:(算法)