完全背包----两个for循环的先后问题
来源:互联网 发布:mac pagedown 编辑:程序博客网 时间:2024/06/07 03:15
这篇文章主要是讲完全背包问题中,什么情况下两个for循环的位置不能交换。
在点击打开链接(完全背包问题----思想的理解)中我们提到,完全背包一维数组的实现的两个for循环是可以交换顺序的。
伪代码分别如下所示:
方式一:《背包九讲》基于01背包问题推导出来的,还记得和01背包一维数组实现的区别吗?
f[0] =0;
for i:1->n
do for j:c[i]->C
f[j] = max(f[j],f[j-c[i]+w[i]])
方式二:《算法竞赛入门》基于DAG推导出
f[0] = 0
for i:1->C
do for j:1->n
if(i>=c[j] && f[i]>f[i-c[j]]+w[i]) f[i] =f[i-c[j]]+w[i];
完全背包问题的要求是要求求出装满背包时的最大重量,在这种情况下,上述两种for循环都是可以的。
但是我们现在来换一个问题:UVa中的674硬币找零问题:点击打开链接
该问题大意如下:
有5种硬币,面值分别为1,5,10,20,25。给你一个总额s,问有多少种找零方式?
注意比如总额为6,则[1,5],[5,1]显然是同一种找零方式,这两种只能算作一种。
问题的分析:
很显然这是一个完全背包模型,但是又不完全相同,因为它要求的是总的找零方式。
换成DAG的描述就是,以前要求从状态S->到状态0的最大路径,而现在问你一共能有多有条路径能从状态S到状态0.而且与点的顺序无关。
状态转移方程很好定义
d[i][j]表示前i种硬币对金额j找零的方式数。则
d[i][j] = d[i-1][j]+d[i-1][j-kc[i]] k:0->j/c[i]
在这种情况下只能采用方式一,把对n的历遍放到第一层循环,这样才能避免把[1,5]、[5,1]算作两条路径。因为你限制了1,5的顺序,
到了i=5之后不可能在发生5,1的情况产生。
对于方式二,把对n的历遍放在第二层,对于任意的一个状态v,都可能历遍每一种硬币,会导致重复冗余的问题。
如果想加深理解,建议最好把两种方式都实现一下,单步执行查看
该问题的具体代码实现如下:
int c[5] = { 1, 5, 10, 25, 50 };int d[7490];int main(){d[0] = 1;for (int j = 0; j<5; ++j){for (int i = c[j]; i <= 11; ++i){d[i] += d[i - c[j]];}}int n;cin >> n;cout << d[n];return 0;}
- 完全背包----两个for循环的先后问题
- 两个并行 for 循环 的问题
- 两个for循环的优缺点
- 两个for循环的优缺点
- 两个for循环的优缺点
- 01背包、完全背包、多重背包问题的C++实现
- 比较两个日期的先后
- 完全背包问题的改进实现
- 完全背包问题----思想的理解
- P1616 疯狂的采药,完全背包问题
- 背包问题-完全背包-背包问题
- 01背包 完全背包问题
- 背包问题2:完全背包
- 01背包+完全背包问题
- 两个for/if循环的优缺点
- java中两个for循环的区别
- 背包问题-完全背包-贪吃的大嘴
- nyoj311完全背包(完全背包问题)
- 图片预加载
- POJ 1611 The Suspects 并查集
- 基于centos6.5快速搭建jdk,tomcat,nginx,显示个人静态页面(基于yum)
- River Hopscotch--二分答案
- <bitset> 简单使用
- 完全背包----两个for循环的先后问题
- js的Prototype属性 解释及常用方法
- JAVA对象创建加载过程。
- linux命令大全之crontab命令使用详解 linux crontab 时间设置
- 【7】Reverse Integer
- Struts2+Spring+Hibernate
- 出现"无法连接synaptics定点装置驱动程序" 的解决方法
- linux:php配置文件php.ini详解
- 最长上升子序列的初步学习