今天在看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) j
(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;
}