POJ 1742 多重背包问题
来源:互联网 发布:app软件著作权范本 编辑:程序博客网 时间:2024/04/28 10:26
在《背包九读》里,作者提到了最后的一种基本背包问题是多重背包问题
在所有背包问题中,问题都是一致的:有若干个物体,P(Wi, Vi) ,每个重量用wi表示,选择后能获得的价值用Vi表示。然后有一个总容量,在满足不超过总容量的情况下,使得选择的物体尽量价值最大。
01背包中,物体只有一个要么选,要么不选。
在 完全背包问题中,每个物体都有无数个,也可以选择无数个。
在 多重背包中,物体的个数是受限的,用P(Wi, Vi, Ai)表示。最大可以选择Ai个。
在《背包九读》中,作者给出一种思路是将多重背包问题,拆解成01背包,拆解的原则是将物体分解。
假如我们有13个物体,那么如何分解成一组整数,使得他们的组合可以表示出 1 - 13中的任意一个呢,作者给出的思路是利用二进制的分解方法,将一个整数分解出 1 2 4 ...等因子。
但是最后一个因子是有学问的,因为我们不能使得分解出来的所有数的和大于Ai,所以最后一个数是 Ai - (1+2+...2^(k-1)) = Ai - (2^k - 1) > 0
所以上面的解就是将之分解为 1 2 4 6 这样的基。 然后将 1倍的物体i理解成新物体,2倍的物体i理解成一个新的物体.....
复杂度降低到 O(N * M * log(A)).
不过这个算法看起来似乎仍然没有那么漂亮。没有aha的感觉吧
楼教主的思路貌似不怎么好理解吧,感觉网上广泛流行的是使用如下的手段来做转换:从完全背包转换成多重背包问题。
当在处理 第 i 中硬币的时候,我们记录 获得每一个金钱值 所需要的 当前硬币的数量,如果这个数量满足条件(小于等于给定的数目),我们才会选择这中硬币,否则不会。
用一个数组,我们将完全背包问题加以限制,就实现了一个多重背包。
代码如下:
#include <stdio.h>#include <string.h>#define COIN_NUM 105#define MONEY_SUM 100005int coin[COIN_NUM];int amount[COIN_NUM];int dp[MONEY_SUM];int used[MONEY_SUM];int nCoin, nSum;int GetNumOfPayments(){memset(dp, 0, sizeof(dp));dp[0] = 1;int i ,j;for(i = 0; i < nCoin; i++){memset(used, 0, sizeof(used));for( j = coin[i]; j <= nSum; j++){
//因为这个问题仅仅是 求出是否即可,所以用bool就可以实现if(dp[j-coin[i]] && !dp[j] && used[j-coin[i]] + 1 <= amount[i]){dp[j] = 1;used[j] = used[j-coin[i]] + 1;}}}int nTotal = 0;for( i = 1; i <= nSum; i++){nTotal += dp[i];}return nTotal;}int main(){int i,j;while(scanf("%d%d", &nCoin, &nSum) != EOF){if(nCoin == 0 && nSum == 0){break;}for(i = 0; i < nCoin; i++){scanf("%d", coin + i);}for( i = 0; i < nCoin; i++){scanf("%d", amount + i);}printf("%d\n",GetNumOfPayments());}return 0;}
代码的复杂度是 O(N*M)应该是一个比较不错的解法了~
总之来说今天收获还是很大的,弄清楚了几个基本类型的背包问题,AC了四个相关练习,为接下来找工作又多了一份自信。
准备明天挑战FB的 Online Puzzle,好运~
- POJ 1742 多重背包问题
- POJ 1742多重背包问题
- POJ 1742 多重背包问题
- poj 1742 Coins(多重背包可行性问题)
- poj 1742 多重背包算法优化问题
- poj 1742 Coins (多重背包可行性问题)
- poj 1742 多重背包可行性问题
- poj-1742 COINS(多重背包问题)
- poj 1742 Coins【多重背包可行性问题】
- POJ 1742 多重背包
- poj 1742 多重背包
- poj 1742多重背包
- poj 1742 多重背包
- poj 1742(多重背包)
- POJ 1742 多重背包
- POJ 1276 多重背包问题
- poj 1276 多重背包问题
- 多重背包问题 POJ 1014
- C语言入门教程 (十五) 指针概念
- NS2 trace文件分析脚本(适合无线trace)
- C语言入门教程 (十六) 数组和指针
- hdu 1028
- 小故事,大道理
- POJ 1742 多重背包问题
- C语言入门教程 (十七) 指针函数和函数指针
- ruby线程控制,线程同步
- 如何学习C语言(4)-----讲座稿
- C语言入门教程 (十八) 结构体
- Notification使用详解之四:由后台服务向Activity发送进度信息
- 鼠标单击点在世界坐标系中的射线 计算原理
- Hadoop重启需要格式化的问题
- RHEL5笔记(以前的)