背包问题——“01背包”最优方案总数的求解
来源:互联网 发布:厦门大学网络教育 编辑:程序博客网 时间:2024/06/05 08:11
回忆一下01背包的动态规划状态及状态方程:
设背包容量为M,一共有N件物品,每件物品质量为weight[i],每件物品的价值为value[i]。
1) 子问题定义:dp[i][j]表示前i件物品中选取若干件物品放入剩余容量为j的背包中所能得到的最大价值。
2) 根据第i件物品放或不放进行决策。
详细细节就不再多说了,我们直接进入正题。
在这里的话,最优方案总数就是物品总价值最大的方案数,那要怎么求呢?
我们设kry[i][j]为dp[i][j]的方案数,那么最优方案总数就是kry[N][M],我们分析下怎么求kry[i][j],对于01背包来说:
经过max函数取最大值后,如果dp[i][j]==dp[i-1][j] 或者 dp[i][j]==dp[i-1][j-weight[i]]+value[i] ,那么kry[i][j] = kry[i-1][j] 或者 kry[i][j] = kry[i-1][j-weight[i]]。也就是说,对于dp[i][j]==dp[i-1][j] 时,表明第i件不放入时价值更大,那么到状态[i][j]的方案数就应该等于到状态[i-1][j]的方案数。同理,如果dp[i][j]==dp[i-1][j-weight[i]]+value[i],说明第i件放入时价值更大,此时到状态[i][j]的方案数就应该等于到状态[i-1][j-weight[i]]的方案数。
而若dp[i-1][j] ==dp[i-1][j-weight[i]]+value[i],],则说明即可以通过状态[i-1][j]在不加入第i件物品情况下到达状态[i][j],又可以通过状态[i-1][j-C[i]]在加入第i件物品的情况下到达状态[i][j],并且这两种情况都使得价值最大且这两种情况是互斥的,那么此时kry[i][j] = kry[i-1][j] + kry[i-1][j-weight[i]](你可以这样理解:两种到目前的状态[i][j]的方案都是最优解,那最优解的方案总数就是两个最优解的方案数相加)。
还有一点需要注意的,就是kry[][]必须全部初始化为1。因为无论dp[i][j]中i, j的值是多少,dp[i][j]总是存在的,既然存在,那就说明至少有一种方案,因此初始化为1。这里可能有些难以理解,没事,先记着,慢慢就会懂了。
“Talk is cheap, show me the code.”
for(int j=0; j<maxm; j++ ) kry[j] = 1;memset(dp, 0, sizeof(dp));for( int i=1; i<=n; i++ ){ for( int j=1; j<=m; j++ ) { dp[i][j] = dp[i-1][j]; kry[i][j] = kry[i-1][j]; if( j>=w[i] ){ if( dp[i][j]<dp[i-1][j-w[i]]+1 ) { dp[i][j] = dp[i-1][j-w[i]] + 1; kry[i][j] = kry[i-1][j-w[i]]; } else if( dp[i][j]==dp[i-1][j-w[i]]+1 ) kry[i][j] = kry[i-1][j] + kry[i-1][j-w[i]];} }}
同理,也可以用一维重复数组来求最优方案总数:
fill(kry, kry+maxm, INF );memset(dp, 0, sizeof(dp));for( int i=1; i<=n; i++ ){ for( int j=m; j>=w[i]; j-- ) { if( dp[j]<dp[j-w[i]]+1) { dp[j] = dp[j-w[i]] + 1; kry[j] = kry[j-w[i]]; } else if( dp[j]==dp[j-w[i]]+1) kry[j] = kry[j] + kry[j-w[i]]; }}
- 背包问题——“01背包”最优方案总数的求解
- 背包问题——“01背包”最优方案总数分析及实现
- 背包问题——“完全背包”最优方案总数分析及实现
- 背包问题——“01背包”及“完全背包”装满背包的方案总数分析及实现
- 背包问题----完全背包(最优方案总数分析及实现)
- 背包问题---01背包最优方案总数(原理剖析代码实现)
- 背包问题---01背包|完全背包(装满背包的方案总数分析及实现)
- “01背包”最优方案总数分析及实现
- 求背包方案总数,最优背包方案数
- 用回溯法求解0—1背包问题,并输出问题的最优解
- 背包问题--输出最优方案
- 完全背包”最优方案总数分析及实现 结合实际例题
- 01背包”及“完全背包”装满背包的方案总数分析及实现
- 01背包问题的求解
- 最优装载问题或者01背包问题的分支限界法求解
- 背包问题——“01背包”详解及实现(包含背包中具体物品的求解)
- 背包问题——“01背包”详解及实现(包含背包中具体物品的求解)
- 背包问题——“01背包”详解及实现(包含背包中具体物品的求解)
- 分布式与集群的区别
- Tomcat下热部署
- 数学篇----参数估计之最大似然估计法[概率论]
- 《coredump问题原理探究》Linux x86版6.6节单继承
- 15.02.04,C数据类型笔记
- 背包问题——“01背包”最优方案总数的求解
- Error: EMFILE, too many open files 'xxx.ejs'
- cocoapods 找不到头文件
- Play on Words——字母首尾相连
- ArrayList
- 常用CSS样式总结
- 本文整理了四种在MySQL中修改root密码的方法
- 初次在Android上运行opencv app时,出现的错误,以及解决
- C/C++堆和栈的区别