01背包 Hdu Bone Collector(2602)d
来源:互联网 发布:applocale类似的软件 编辑:程序博客网 时间:2024/06/05 09:12
我在学习01背包的时候也遇到过各种的困难,不能很好地理解01背包里的数组值得变化。
在这我希望以最简单的方式讲给大家,当然写的也比较啰嗦
01背包是背包里最简单的,本人刚刚做完背包的问题,把自己的学习总结讲给大家,这只是本人的理解,希望大牛看出哪里有错误指出。
01背包的状态转移方程:f[i, j] = max( f[i-1, j-Wi] + Pi , f[i-1, j] )
这个方程是伪代码写的。i表示有第几件物品,j代表你拥有的费用。max()是你自己定义的一个比较函数。
i表示物品。
j表示费用。
wi表示第i个的费用。
pi表示第i个的价值。
f[ i , j ]表示的是你在面对第i个的时,你有j的费用。
f[ i -1,j ]表示的是你在上一物品选取的时候,有j费用的最优选择。
f[ i-1 ,j-wi ]表示的是你在上一个物品时,拥有j -wi费用的时候的最优选择。
用代码实现时的代码是
for(i=1;i<=n;i++) //i表示第几个物品for(j=0;j<=m;j++)//j表示费用if(j>=cost[i])//当费用大于或等于当前的花费是,才可以进行赋值,否则无法放入,也就是数组会越界pet[i][j]=Max(pet[i-1][j],pet[i-1][j-cost[i]]+value[i]);//转移方程,用cost[i]表示第i个所要花费的费用,vale[i]表示第i个物品的费用elsepet[i][j]=pet[i-1][j];//不大于的时候跟新数组里的信息
现在大家一定充满疑问就是为什么这样就可以完成,我给大家举一个例子,或许大家就可以理解了。
题目选自杭电的2602题http://acm.hdu.edu.cn/showproblem.php?pid=2602
15 101 2 3 4 55 4 3 2 1
这一题是最基本的01背包问题。
不明白题意的自行百度翻译
我给大家ac的代码
<pre name="code" class="cpp">#include<stdio.h>#include<string.h>int pet[1001][1001];int value[1001],cost[1001];int Max(int a,int b){ return a>b?a:b;}int main(){ int t,i,j,n,m; scanf("%d",&t); while(t--) { memset(pet,0,sizeof(pet)); scanf("%d %d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&value[i]); for(i=1;i<=n;i++) scanf("%d",&cost[i]); for(i=1;i<=n;i++) for(j=0;j<=m;j++) if(j>=cost[i]) pet[i][j]=Max(pet[i-1][j],pet[i-1][j-cost[i]]+value[i]); else pet[i][j]=pet[i-1][j]; printf("%d\n",pet[n][m]); } return 0;}
给大家一个数组值的变化表,希望大家可以看清这个表的变化
第一排表示0~10表示背包的费用
第一个竖排表示0~5表示的是价值,第二个5~1是表示费用
我们要学会的就是如何填这个表
也就是理解算法计算问题的关键点.
0
1
2
3
4
5
6
7
8
9
10
0(0)
0
0
0
0
0
0
0
0
0
0
0
1(5)
0
0
0
0
0
1
1
1
1
1
1
2(4)
0
0
0
0
2
2
2
2
2
3
3
3(3)
0
0
0
3
3
3
3
5
5
5
5
4(2)
0
0
4
4
4
7
7
7
7
9
9
5(1)
0
5
5
9
9
9
12
12
12
12
14
for(i=1;i<=n;i++) for(j=0;j<=m;j++) if(j>=cost[i]) pet[i][j]=Max(pet[i-1][j],pet[i-1][j-cost[i]]+value[i]); else pet[i][j]=pet[i-1][j];
循环i=1开始,第一件物品费用为5,价值1
第一次进入for循环,j=1,费用为5,进入else pet[ 1 ][ 1 ]=pet[ 0 ][ 1 ];
第二次进入 j=2,费用还是为5 ,进入else petp[1][2]=pet[0][1];
。。。。。。
第五次进入 j=5 进入if(j>=cost[i]) pet[ 1 ][ 5 ]=max(pet[ 0 ][ 5 ],pet[ 0 ][5-cost[i]]+value[i]);可以看出来 cost[i]=5,value[i]=1, pet[ 0 ][ 5 ]=0,pet[ 0 ][ 5-cost[ i ] ]+value[ i ] = 1。pet[ 1 ][ 5 ]=1。
第六次进入j=6 进入if(j>=cost[i]) pet[ 1 ][ 6 ]=max(pet[ 0 ][ 6 ],pet[ 0 ][6-cost[i]]+value[i]);可以看出来cost[i]=5,value[i]=1, pet[ 0 ][ 6 ]=0,pet[ 0 ][ 6-cost[ i ] ]+value[ i ] = 1。pet[ 1 ][ 6 ]=1。
。。。。。。
循环i=2,第二件价值为2,费用为4
第一次进入,j=1,费用为4,不够,进入else pet[ 2 ][ 1 ]=pet[ 1 ][ 1 ]。
第二次进入,j=2.。。。。。。。。
。。。。。。
第四次进入,j=4,费用为4,进入if(j>=cost[ i ])pet[ 2 ][ 4 ]=max(pet[ 1 ][ 4 ],pet[ 1 ][4-cost[ i ] ]+value[ i ]),
pet[ 1 ][ 4 ]=0,pet[ 1 ][ 4-cost[ i ] ]+value[ i ]=2; 所以pet[ 2 ][ 4 ]=2;
第五次进入,j=5,费用为4,进入if( j>=cost[ i ] ) pet[ 2 ][ 5 ]=max( pet[ 1 ][ 5 ] ,pet[ 1 ][ 5-cost[ i ] ]+value[ i ] ).
比较值pet[ 1 ][ 5 ]=1,pet[ 1 ][ 1 ]+value[ i ]=2,所以pet[ 2 ][ 5 ]=2。
。。。。。。
每加上一个物品,从0到10容量的背包根据上一次存的内容(上一次是以前所有物品加上后的最大价值),求出这一次加上该物品最大的价值。
大家如果还不理解的话多看几遍就可以理解了,试着把表填一填。
如果有错还希望大家指出,谢谢!!
- 01背包 Hdu Bone Collector(2602)d
- hdu 2602 Bone Collector (01背包)
- hdu 2602 Bone Collector(01背包)
- HDU 2602 Bone Collector( 01背包 )
- HDU 2602 Bone Collector(01背包)
- HDU 2602 Bone Collector(01背包)
- HDU 2602 Bone Collector (01背包)
- HDU 2602 Bone Collector(01背包)
- HDU 2602 Bone Collector(01背包)
- hdu 2602 Bone Collector (01背包)
- hdu 2602 Bone Collector(01背包)
- HDU 2602 Bone Collector(01背包)
- HDU - 2602 Bone Collector (01背包)
- HDU 2602 Bone Collector (01背包)
- HDU 2602 Bone Collector (01背包)
- HDU 2602 Bone Collector(01背包)
- hdu 2602 Bone Collector(01背包)
- HDU 2602 Bone Collector(01背包)
- uva 12589 Learning Vector
- 思考项目 求1到m的平方和
- 【Linux】【CGI】CGIC库的移植及使用
- android避免弹出软键盘遮盖listview
- Handler详解系列(二)——主线程向自身消息队列发消息
- 01背包 Hdu Bone Collector(2602)d
- 第七周项目3(2)求三数最大值
- 【Linux】【CGI】用CGIC库来开发CGI程序
- 第七周项目三(1)求两数正差值
- Handler详解系列(一)——Handler异步消息机制详解(附图)
- 学到老活到老
- 关于正则表达式——元字符
- 做java开发这一年
- 【Linux】【CGI】cgic: CGI的C函数库