01背包问题
来源:互联网 发布:漂亮的登录界面源码 编辑:程序博客网 时间:2024/06/07 08:15
版权声明:本文为博主原创文章 http://blog.csdn.net/su20145104009
给大家附上一个题目吧,便于理解
ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。
输入:每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v
接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w
01背包其实就是遍历所有可能情况 然后取最优的结果 和搜索差不多 不过比搜索快
0 1 背包的方程为dp[i]=max(dp[i-c[j]])+w[j],dp[i])
i:表示当前的背包容量
j:是苹果的序号
dp[i]:是容量为i的背包能放的最大价值
c[j]:序号为j的苹果的大小
w[j]:序号为j的苹果的价值
这个方程翻译成白话文就是 容量为i的背包的最大价值=(当前背包容量-序号为j的苹果的大小)的最大价值+序号为j的苹果的价值 和 容量为i的背包的当前价值 之间的最大值
说着比较绕口。慢慢理解
说白了 ,其实就是取与不取的问题 ,如果取了 那么取后的价值要大于我没有取之前的价值 否则我就不要你 (因为同样大小的背包我要装价值更大的啊)
对着这道题举个例子吧
5 10
1 9
4 4
2 6
5 5
10 8
你能根据自己的想法填下表吗 看结果是否和我的一样
这个结果其实就是根据0-1背包的思想得到的 ,如果你能填 证明你已经入门了
我首先附上0-1背包的代码
- for(int i=0;i<n;i++)
- {
- for(int j=v;j>=0;j--)
- {
- if(j>=c[i])
- dp[j]=max(dp[j-c[i]]+w[i],dp[j]);
- }
- }
你肯定有几个问题?
1.为什么外层循环是苹果的数目 而不是背包的容量
答:因为每个苹果只能选择一次 如果背包容量在外
2.外循环是对苹果的遍历 那么内循环为什么是v-》0而不是 从0-》v
这个问题我也迷惑了好久 我们仔细看看动态方程dp[i]=max(dp[i-c[j]])+w[j],dp[i]) 我们首先假设 有一个苹果大小为1 价值为9
那么dp[1]=max(dp[1-1]+9,dp[1])=9 是正常的 dp[2]=max(dp[2-1]+9,dp[2])=18..dp[3]=27,dp[4]=36等等 发现问题了吧
所以内循环从0-》v是错误的 如果从v-》0就行了 因为在每个苹果循环的时候 我们要保证当前已经遍历的背包对我未遍历的背包没有影响
看完了这些 分析上面的截图吧
首先是对苹果大小为1 价值为9 背包容量为10.....1 最大价值都为9 背包容量为0 最大价值为0
苹果大小为4 价值为4 背包容量为10.....5的价值变为13 为什么呢 还是动态规划方程dp[i]=max(dp[i-c[j]])+w[j],dp[i]) 分析一个为5的吧 dp[5]=max(d[4]+4,dp[5])=9+4=13 而在背包容量为4的时候 我们发现价值还是9 没有变化因为这两个苹果大小4+1=5>4
由于我们对每个苹果遍历后 都是当前苹果个数的最优结果 所以当我们遍历完最后一个苹果 那么结果也就是最优化的
就分析这么多吧
这道题的传送门 和AC代码
- #include <stdio.h>
- #include <string.h>
- int main()
- {
- int n,v,max,c[1005],w[1005],dp[1005];
- while(scanf("%d %d",&n,&v)!=EOF)
- {
- if(n==0&&v==0)
- break;
- memset(dp,0,sizeof(dp));
- for(int i=0;i<n;i++)
- scanf("%d %d",&c[i],&w[i]);
- max=0;
- for(int i=0;i<n;i++)
- for(int j=v;j>=c[i];j--)
- {
- // dp[j]=dp[j];
- if(dp[j]<dp[j-c[i]]+w[i])
- dp[j]=dp[j-c[i]]+w[i];
- if(max<dp[j])
- max=dp[j];
- }
- printf("%d\n",max);
- }
- return 0;
- }
- 背包问题---01背包
- DP 背包问题 01背包
- 01背包--苹果,背包问题
- 01背包 完全背包问题
- 背包问题之01背包
- 背包问题之01背包
- 背包问题1:01背包
- 背包问题《1》01背包
- 01背包+完全背包问题
- 背包问题-背包01-苹果
- 背包问题之01背包
- 背包问题(01背包,完全背包,多重背包)
- 背包问题(01背包,完全背包,多重背包)
- 动态规划-----背包问题-----01背包,完全背包,多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 背包(01背包、完全背包、多重背包)问题总结
- 背包问题(01背包,完全背包,多重背包)
- 经典背包问题 01背包+完全背包+多重背包
- 网站Session(会话)保持的常用手段
- Android屏幕适配全攻略
- 读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数
- 【Dongle】【MVC】MVC框架学习
- C#string 的引用类型问题
- 01背包问题
- BZOJ 1001 [BeiJing2006]狼抓兔子 最短路
- 使用ajax编写异步查询
- Android快速发布项目到jcenter
- 计算机网络
- linux搭建网桥
- 最短路径问题平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。
- 备忘录模式
- 09 事件驱动的OSAL简要分析