hdoj 2191 多重背包入门题
来源:互联网 发布:漫画上色软件 编辑:程序博客网 时间:2024/05/07 03:55
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191
该题目为裸的多重背包 入门题。。纯粹用来检测自己对背包九讲的理解。。
结果WA了居然因为忘记了多组数据的循环语句。。果然太久没写,写的越来越渣。。
此处采用的第一种方法为转化为01背包问题,并没有进行优化。。
状态转移方程为F[i ,v] = max {F[i − 1,v − k ∗ C i ] + k ∗ W i | 0 ≤ k ≤ M i }
然后我们依然可以转化为一维数组来进行求解。。。
此处附上该方法的代码:
#include<iostream>#include<cstring>using namespace std;int c[110];int w[110];int m[110];int dp[110];int max(int a,int b){return (a>b)?a:b;}int main (){int t,n,V;cin >> t;while(t--){memset(dp,0,sizeof(dp));cin >> V >> n;for(int i = 1;i <= n;i++)cin >> c[i] >> w[i] >> m[i];for(int i = 1;i <= n;i++){for(int j = V;j >= c[i];j--){for(int k = 1;k <= m[i] && k*c[i] <= j;k++) //保证 k不超过该物品的个数,且花费不能超过经费 dp[j] = max(dp[j],dp[j-k*c[i]]+k*w[i]);}}cout << dp[V] << endl;}return 0;}然后一种方法是转化成二进制的方法。背包九讲中时这样说的:
仍然考虑二进制的思想,我们考虑把第 i 种物品换成若干件物品,使得原问
题中第 i 种物品可取的每种策略——取 0...M i 件——均能等价于取若干件代换
以后的物品。另外,取超过 M i 件的策略必不能出现。
方法是:将第 i 种物品分成若干件01背包中的物品,其中每件物品有一个系
数。这件物品的费用和价值均是原来的费用和价值乘以这个系数。令这些系数
分别为 1,2^2,2^3 , ...2 k−1 ,M i − 2 k + 1 ,且 k 是满足 M i − 2 k + 1 > 0 的最大整数。例
如,如果 M i 为 13 ,则相应的 k = 3 ,这种最多取 13 件的物品应被分成系数分别
为 1,2,4,6 的四件物品。
分成的这几件物品的系数和为 M i ,表明不可能取多于 M i 件的第 i 种物品。另
外这种方法也能保证对于 0...M i 间的每一个整数,均可以用若干个系数的和表
示。这里算法正确性的证明可以分 0...2 k−1 和 2 k ...M i 两段来分别讨论得出,
希望读者自己思考尝试一下。
伪代码如下:
def MultiplePack( F , C , W , M )
if C · M ≥ V
CompletePack( F , C , W )
return
k := 1
while k < M
ZeroOnePack( kC , kW )
M := M − k
k := 2k
ZeroOnePack( C · M , W · M )
思考了一下感觉伪代码中的拆分方式并不是跟前文的一样,,伪代码中是将背包中的拆分成 1,2^2,2^3,....2^k, m - 2^k, 且k是满足m - 2^k > 0 的最大整数。。
这样不管拿几个该物品也可以将所有方式都表示出来,所以应该是一样的。。
于是将该方法实现了一下。。
代码如下:
#include<iostream>#include<cstring>using namespace std;int w[110];int c[110];int m[110];int dp[110];int max(int a,int b){return (a>b) ? a:b;}int main (){int t,n,V;cin >> t;while (t--){memset(dp,0,sizeof(dp));cin >> V >> n;for(int i = 1;i <= n;i++)cin >> c[i] >> w[i] >> m[i];for(int i = 1;i <= n;i++){if(c[i]*m[i] >= V){for(int j = c[i];j <= V;j++)dp[j] = max(dp[j],dp[j-c[i]]+w[i]); }else {int k = 1;while (k < m[i]){for(int j = V;j >= k*c[i];j--)dp[j] = max(dp[j],dp[j-k*c[i]]+k*w[i]);m[i] = m[i] - k;k = 2*k;}for(int j = V;j >= c[i]*m[i];j--) //此为拆到最后的那个 m - 2^k的物品 dp[j] = max(dp[j],dp[j-m[i]*c[i]] + m[i]*w[i]); }}cout << dp[V] << endl;}return 0;}
- hdoj 2191 多重背包入门题
- HDOJ 2191 多重背包问题
- hdu 2191 多重背包入门
- 多重背包——HDOJ 2191
- hdoj 4945 多重背包
- 多重背包 hdoj
- HDOJ 1059 Dividing (多重背包)
- hdoj 1171 多重背包问题
- hdoj-2844-Coins【多重背包】
- (DP,多重背包) Coins --HDOJ
- POJ 1742 Coins 多重背包入门题
- HDOJ 2192多重背包 01背包模板
- hdoj 2191 悼念512。。 【多重背包】+【二进制分解】
- HDOJ 2191 珍惜现在,感恩生活(多重背包)
- hdoj 1114 完全背包入门题
- hdoj 2602 01背包入门题
- poj 1742 多重背包入门
- poj 1014 多重背包入门
- 【C#】变量的定义,值、引用以及枚举类型详解说明
- s4
- 【bzoj3223】文艺平衡树【Splay】【呵呵】
- Thrift 非阻塞式IO服务模型-TNonblockingServer
- uva_10878
- hdoj 2191 多重背包入门题
- 黑马程序员__内部类和异常
- 我喜欢网站
- c#实现直角排列的99乘法表
- Thrift 半同步半异步的服务模型-THsHaServer(异步调用客户端)
- oracle学习笔记
- 天气预报调用插件
- EClipse设置智能输入
- android studio安装流程