0/1背包

  • 一、Bone Collector
    • 解法一:二维数组解法(0/1背包模板代码)
      • 1.1 0/1背包打印方案代码
    • 解法二:滚动数组(一维)解法
      • 2.1 一维滚动数组例题
    • E-爱玩游戏的Tom

一、Bone Collector

Problem Description
许多年前,在泰迪的家乡,有一个人被称为“骨收集者”。骨头收集者有一个大袋子,里面装满了V,在收集骨头的过程中,不同的骨骼具有不同的值和不同的体积,现在给定每个骨骼的值,您能否计算出骨骼收集器可获得的总值的最大值?

Input
第一行包含整数T,即案例数。
紧随其后的是T个案例,每个案例三行,第一行包含两个整数N,C(N <= 1000,C <= 1000),
表示骨头的数量和包的体积。第二行包含代表每个骨骼值的N个整数。第三行包含N个整数,代表每个骨骼的体积。

Output
每行一个整数,代表总和的最大值(该数字将小于231)。

Sample Input

1
5 10
1 2 3 4 5
5 4 3 2 1

Sample Output

14

解法一:二维数组解法(0/1背包模板代码)

tip:注意多组数据要清dp数组为零,忘记了所以wa了一次。


一道模板题~根据上次讲解的0/1背包推导公式(0/1背包讲解戳这里~.),并用条件语句实现公式即可。
二维表是N+1行(第0行是前0个物品的情况,也就是没有东西可以装),
C+1(第0列是背包0容量的情况)。
第0行和第0列的dp数组值都是0,其他根据公式填入,最大(最优)的情况就是二维数组的最右下角那个格子的值即dp[N][C]。

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;const int maxn = 1e3+1;
int N, C;
int dp[maxn][maxn];
struct {int v;int n;
}node[maxn];
void back() {for (int i = 0; i <= N; i++) dp[i][0] = 0;  for (int i = 1; i <= N; i++) {for (int j = 0; j <= C; j++) {if (node[i].n > j) { //第i个物品太大装不下dp[i][j] = dp[i-1][j];} else {//第i个物品可以装,选择装或不装,选择两种情况结果最大的。dp[i][j] = max(dp[i-1][j-node[i].n]+node[i].v, dp[i-1][j]);}}}
}
int main() {fioint T;cin >> T;while (T--) {cin >> N >> C;memset(dp, 0, sizeof(dp));for (int i = 1; i <= N; i++) cin >> node[i].v;for (int i = 1; i <= N; i++) cin >> node[i].n;back();cout << dp[N][C] << endl;}
}

1.1 0/1背包打印方案代码

判断所填的值dp[i][j]是等于dp[i-1][j-ni]+vi还是dp[i-1][j]
用条件语句直接判别两种情况:

  1. 若等于dp[i-1][j-ni]+vi,则a[i]=1,表明选了第i个物品,j更新为j-ni
  2. 若等于dp[i-1][j],a[i]=0(不用赋值,已初始化),表明没选第i个物品,j不更新。

两种情况 i 都要减1。

int a[maxn];//记录解的数组void output() {int i = N, j = C;int r = N;while (r--) {if (dp[i][j] == (dp[i-1][j-node[i].n]+node[i].v)) {j = j-node[i].n;a[i] = 1;}i -= 1;}for (int i = 1; i <= N; i++)if (a[i])cout << i << " ";
}

解法二:滚动数组(一维)解法

适合:N、C非常大的情况
不适合:需要打印具体方案

把二维dp[][]变成一维的dp[],这个解放可以节省更多的空间。二维dp[][]中每一行是由上一行计算出来的,所以只跟上一行有关。
故我们可以直接用新的一行覆盖原来一行

int dp[1001];void back() {memset(dp, 0, sizeof(dp));for (int i = 1; i <= N; i++) for (int j = C; j >= node[i].n; j--) dp[j] = max(dp[j], dp[j-node[i].n]+node[i].v);cout << dp[C] << endl;
}

初始化为0,第一次dp是从物品1开始,倒着从最大容量往物品的重量的方向依次填入值(也就是图中以5为分界,5前面的位置填原来的值,不更新;5后面的值计算填入),倒着计算可以省掉前面几个不必计算的空格,减少计算量。

重复上述覆盖操作,即可得到第五次dp的结果,取dp[N]即是最优解。

2.1 一维滚动数组例题

E-爱玩游戏的Tom

题目链接

题目描述
Tom很喜欢玩游戏,他在电脑上下了《GTA5》和《微软飞行模拟》,对于后者他还丧心病狂的下载了所有地图包,导致他可用空间只有mGM,但他还有几个学校要求安装的软件没有下载,他不能全部放下去,因此只能选择性的安装一部分。现在,我们知道每个学习软件的大小以及该学习软件的重要程度,现在Tom找到你,应该安装哪一些软件,使得这些软件的重要程度之和最大。
对于输入第一行有n(0 < n < 100)和m(0 < m < 10000)两个整数组成,n代表接下来的输入行数,m代表可用空间还剩mGB。
接下来的n行,每行两个整数,前一个整数为每个学习软件的大小(GB),后一个整数代表重要程度。
对于输出,只有一行,即为最大重要程度之和。

输入描述:
第一行输入n和m,n代表接下来的行数,m代表可用空间剩余内存,整数之间空格隔开
接下来的n行,由两个整数组成,前一个为每个软件大小,后一个整数代表重要程度,整数之间空格隔开

输出描述:
输出只有一行且只有一个整数,即为最大重要程度之和

示例1
输入

3 23
15 9
20 5
7 7

输出

16

说明
1、输入:
第一行3表示接下来有3行,23表示还剩23GB
第一行后的三行前一个整数表示学习软件大小(GB),后一个整数表示重要程度
2、输出:
16,表示最大重要程度之和,安装的软件为15GB的和7GB的

AC代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll dp[maxn];
ll t, n, v;
struct node {int vi, wi;
} w[maxn];ll ans() {memset(dp, 0, sizeof(dp));for (int i = 1; i <= n; ++i)for (int j = v; j >= w[i].wi; --j)dp[j] = max(dp[j], dp[j - w[i].wi] + w[i].vi);return dp[v];
}
int main() {scanf("%lld%lld", &n, &v);for (int i = 1; i <= n; ++i)scanf("%d%d", &w[i].wi, &w[i].vi);printf("%lld\n", ans());
}

HDOJ 2602-Bone Collector(0/1背包模板、打印方案及滚动数组解法)相关推荐

  1. hdu 2602 Bone Collector(01背包)模板

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602 Bone Collector Time Limit: 2000/1000 MS (Java/Ot ...

  2. HD 2602 Bone Collector (0-1背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602 Problem Description Many years ago , in Teddy's ...

  3. HDU 2602 Bone Collector DP(01背包)

    Bone Collector Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Desc ...

  4. hdu 2602 Bone Collector(01背包)

    题意:给出包裹的大小v,然后给出n块骨头的价值value和体积volume,求出一路下来包裹可以携带骨头最大价值 思路:01背包 1.二维数组(不常用 #include<iostream> ...

  5. HDOJ 2639 Bone Collector II (背包)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2639 第K优解问题 其基本思想是将每个状态都表示成有序队列,将状态转移方程中的max/min转化成有序 ...

  6. HDU 2602 Bone Collector - from lanshui_Yang

           题目大意:有n件物品,每件物品均有各自的价值和体积,给你一个容量为 V 的背包,问这个背包最多能装的物品的价值是多少?        解题思路:这是一道0 - 1 背包的简单模板题,也是 ...

  7. 【例1】 0/1背包《信息学奥赛一本通》【解法一】 02

    /* [例1] 0/1背包<信息学奥赛一本通>[解法一] 02 http://ybt.ssoier.cn:8088/problem_show.php?pid=1267 */ #includ ...

  8. hdu 2602 Bone Collector 01背包

    Bone Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  9. HDU Problem 2062 Bone Collector【01背包】

    Bone Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

最新文章

  1. 《编写高质量代码:改善c程序代码的125个建议》——第1章 数据,程序设计之根本建议1:认识ANSI C...
  2. python 树_Python树的概念
  3. STM32 基础系列教程 36 - Lwip_dns
  4. SAP中负号前置的函数:CLOI_PUT_SIGN_IN_FRONT
  5. 【leetcode 简单】 第一百一十题 分发饼干
  6. Android高级-Android操作SQL数据管理,增删改查
  7. 获取当前3Ds MAX版本
  8. 作业帮基于 Flink 的实时计算平台实践
  9. worldwind系列教程
  10. 修改UI及盒子启动及部分后续操作
  11. 计算机音乐我还是曾经那个少年,我还是曾经的那个少年什么歌曲
  12. sizebox模型下载_css盒子模型:内联盒模型、width、height、替换元素、边距、border...
  13. 基于51单片机及DS18B20温度传感器数码管显示程序
  14. 勒索病毒锁死文件加密
  15. C++中cout后面输出时加endl和不加endl的区别
  16. java读取rar中的excel文件_java 通用文件下载 excel,pdf,word,jpg,exe,rar
  17. pg_partman
  18. 20145212《Java程序程序设计》课程总结
  19. 深入解析著名的阿里云Log4j 漏洞
  20. 【华为OD机试真题 JS】跳格子游戏

热门文章

  1. 上周热点回顾(4.14-4.20)
  2. TortoiseSVN 不显示图标
  3. Vue版todolist案例
  4. JAVA 可视化日历
  5. webpack快速入门教程
  6. 计算机科学与技术大学生职业规划,计算机科学与技术大学生职业生涯规划ppt
  7. 特殊类型结构--枚举
  8. c语言双向链表 快速排序,双向链表的快速排序(swift版本)
  9. flutter不支持热更新_真当Flutter不能热更新?众能动态化Flutter
  10. 使用git push时, 自动忽略__pycache__文件