由DAG到背包问题——记忆化搜索和递推两种解法
一、问题描述
物品无限的背包问题:有n种物品,每种均有无穷多个。第 i 种物品的体积为Vi,重量为Wi。选一些物品装到一个容量为 C 的背包中,求使得背包内物品总体积不超过C的前提下重量的最大值。1≤n≤100, 1≤Vi≤C≤10000, 1≤Wi≤1000000.
二、解题思路
我们可以先求体积恰好为 i 时的最大重量(设为d[i]),然后取d[i]中的最大值(i ≤ C)。与之前硬币问题,“面值恰好为S”就类似了。只不过加了新属性——重量,相当于把原来的无权图改成带权图,即把“+1”变成“+W[j]”。这样,问题就变成了求以C为起点、终点任意的,边权之和最大的路径。
三、代码实现
1、记忆化搜索
之前纠结这种方法的时间复杂度,先给结果:O(maxn * maxc)。因为计算dp(s)时,如果dp[i]中i是从0-->C,
则dp[i] = max(dp[i],dp[i - V[j]] + W[j]),dp[i - V[j]]已经计算出来且保存,相当于得到dp[i]没有花费时间。如果dp[i]中i是从C-->0,
每次计算的都被保存且只计算一次,有几次小的递归,也相当于没有花费时间。
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std; const int INF = 0x3f3f3f3f;
const int maxn = + ;
const int maxc = + ;
int n,V[maxn],W[maxn],C;
int d[maxc]; //d[i]表示总体积恰好为i时的最大重量 int dp(int s)
{
int& ans = d[s];
if (ans != -) return ans;
ans = - INF;
for (int i = ; i < n; i++)
{
if (s >= V[i]) ans = max(ans, dp(s - V[i]) + W[i]);
}
return ans;
}
void slove()
{
memset(d, -, sizeof(d));
d[] = ;
int res = -;
for (int i = 0; i <= C; i++)
res = max(res, dp(i));
printf("%d\n", res);
} int main()
{
while (scanf("%d",&n) == && n)
{
scanf("%d", &C);
for (int i = ; i < n; i++)
scanf("%d%d", &V[i], &W[i]); slove();
}
return ;
}
2、递推式
这种写法时间复杂度十分显然,与记忆化搜索相同,都是O(maxn * maxc)。但必须注意循环的顺序,比如容量只能从0-->C,而不能反过来,前一种写法则没有循环的顺序要求。
void slove()
{
fill(d, d + n, -INF);
d[] = ;
int res = -;
for (int i = ; i <= C; i++) //容量的循环顺序只能是从小到大
{
for (int j = ; j < n; j++)
{
if(i >= V[j]) d[i] = max(d[i], d[i - V[j]] + W[j]);
}
res = max(res, d[i]);
}
printf("%d\n", res);
}
3、两者比较
在得到状态转移方程之后,还需要思考如何编写程序。尽管在很多情况下,记忆化搜索程序更直观、易懂,但在0-1背包中递推法更理想。因为已知状态转移方程后,递推法的难点是循环顺序,而有了“阶段”定义后,循环顺序变得十分显然。
由DAG到背包问题——记忆化搜索和递推两种解法的更多相关文章
- UVA_437_The_Tower_of_the_Babylon_(DAG上动态规划/记忆化搜索)
描述 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- ACM/ICPC 之 简单DP-记忆化搜索与递推(POJ1088-滑雪)
递推型DP 将每个滑雪点都看作起点,从最低点开始逐个由四周递推出到达此点的最长路径的长度,由该点记下. 理论上,也可以将每一点都看作终点,由最高点开始计数,有兴趣可以试试. //经典DP-由高向低海拔 ...
- 专题1:记忆化搜索/DAG问题/基础动态规划
A OpenJ_Bailian 1088 滑雪 B OpenJ_Bailian 1579 Function Run Fun C HDU 1078 FatMouse and Chee ...
- LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)
题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多. 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以 ...
- bzoj 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果【tarjan+记忆化搜索】
对这个奇形怪状的图tarjan,然后重新连边把图变成DAG,然后记忆化搜索即可 #include<iostream> #include<cstdio> using namesp ...
- 动态规划——I 记忆化搜索
Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道 ...
- 【bzoj1415】[Noi2005]聪聪和可可 期望记忆化搜索
题目描述 输入 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行 ...
- POJ_1088_(dp)(记忆化搜索)
滑雪 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 95792 Accepted: 36322 Description ...
- NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索
矩形嵌套 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a& ...
随机推荐
- 3-6局部变量的存储方式 & 3-7字符型字面值
基础数据类型变量的存储 重点介绍方法级的变量,局势局部变量 存储中怎么存储呢? int n=100; 在栈中开辟内存存储空间. n是内存空间的别名 3-7字符型字面值 单引号不能丢,必须是英文状态. ...
- Codevs 3409 搬运礼物
3409 搬运礼物 CodeVS原创 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 青铜 Bronze 题解 题目描述 Description 小浣熊松松特别喜欢交 ...
- Node.js 内置模块fs(文件系统)
fs模块的三个常用方法 1.fs.readFile() -- 读文件 2.fs.writeFile() -- 写文件 3.fa.stat() -- 查看文件信息 fs模块不同于其它模块的地方是它有异步 ...
- 第三篇 Nosql讲解之windows下Memcached和Memcache的区别安装(二)
一.Memcached和Memcache的区别: 网上关于Memcached和Memcache的区别的理解众说纷纭,我个人的理解是: Memcached是一个内存缓存系统,而Memcache是php的 ...
- SpringBoot | idea新建项目
1.new ----> Spring Initializr 2.设置相应文件名 3.选择需要配置
- gns3 拖出设备显示一个红色的s,无法启动虚拟设备
通过view-docks-调出console窗口,显示错误信息: Error while creating project: Can't connect to server http://172.0. ...
- 获取元素属性 和 获取元素的CSS属性
- python数据结构转换&格式化
列表,元组和字符串python中有三个内建函数:,他们之间的互相转换使用三个函数,str(),tuple()和list(),具体示例如下所示 >>> s = "xxxxx& ...
- 统计最长回文串(传说中的Manacher算法)Hihocoder 1032
算法的核心就在这一句上了:p[i] = min(p[2*id-i], p[id] + id - i); #include <iostream> #include <cstdio> ...
- POJ-1020-Anniversary Cake
链接:https://vjudge.net/problem/POJ-1020 题意: 给一个宽为s的正方形,再给n个变长为an的小正方形, 判断是否能将这n个小正方形完全填充到这个大正方形里面. 思路 ...