DP--完全背包--HDU - 4508
2015-11-05 13:36
375 查看
本题是典型的完全背包问题
for i=1..N
for j=c..V
f[j]=max{f[j],f[j-c]+w}
以上就是这类问题的基本套路
你会发现,这个伪代码与01背包的伪代码只有v的循环次序不同而已。为什么这样一改就可行呢?
首先想想为什么01背包中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态f[v]是由状态f[v-c]递推而来。换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个没有已经选入第i件物品的子结果f[v-c]。
而当前完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果f[v-c],所以就可以并且必须采用v=0..V的顺序循环。这就是这个简单的程序为何成立的道理。
for i=1..N
for j=c..V
f[j]=max{f[j],f[j-c]+w}
以上就是这类问题的基本套路
你会发现,这个伪代码与01背包的伪代码只有v的循环次序不同而已。为什么这样一改就可行呢?
首先想想为什么01背包中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态f[v]是由状态f[v-c]递推而来。换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个没有已经选入第i件物品的子结果f[v-c]。
而当前完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果f[v-c],所以就可以并且必须采用v=0..V的顺序循环。这就是这个简单的程序为何成立的道理。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 110; int dp[maxn], a[maxn], b[maxn]; int main() { int n, m; while(~scanf("%d", &n)) { for(int i=0; i<n; i++) scanf("%d%d", &a[i], &b[i]); scanf("%d", &m); memset(dp, 0, sizeof(dp)); for(int i=0; i<n; i++) for(int c=b[i]; c<=m; c++) dp[c] = max(dp[c], dp[c-b[i]] + a[i]); printf("%d\n", dp[m]); } return 0; }
相关文章推荐
- search
- QT笔记:数据库总结(一)
- iOS手势解锁
- 如何防范SQL注入式攻击
- linux运维超级工具--sysdig
- 解决Jenkins console输出乱码
- * 引领华为:任正非的七大领导力启示
- NAVICATE 修改存储过程提示PROCEDURE _Navicat_Temp_Stored_Proc already exists 解决方法
- 运维小命令
- ListView透明背景点击设置
- IOS特定条件上UITABLEVIEWCELL不刷新的现象
- Leetcode: Longest Increasing Subsequence
- ios开发时,在Xcode中添加多个targets进行版本控制
- Ajax 请求的http头信息特点 x-requested-with
- Operating System: Three Easy Pieces ---An Example: Thread Creation (Note)
- 机器学习逻辑回归模型总结——从原理到sklearn实践
- android 学习路线指南
- dba_jobs与dba_scheduler_jobs的不同
- 使用VAssistX为VS2008 c++代码添加函数头注释
- mysqldump使用