NYOJ 题目860 又见01背包
2016-05-05 21:09
176 查看
描述
有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W
的物品,求所有挑选方案中物品价值总和的最大值。
1 <= n <=100
1 <= wi <= 10^7
1 <= vi <= 100
1 <= W <= 10^9
输入多组测试数据。
每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。
输出满足题意的最大价值,每组测试数据占一行。
样例输入
样例输出
分析:这道题其实和一般的01背包没有什么区别,只是这道题目按照正常的思维去做不行了,因为容量太大,开个10^9的数组开不了,所以这时候就需要换种思维。
这道题很容易发现其实重量很大,达到10^9,但是价值很小啊,现在就来推一下这个所谓的“互换”是怎么来的 (其实我觉得还不如从最原始的来,不叫做“互换”好理解点), 最原始的那个式子dp[i][j]表示当取 i 个, 重量为 j 的时候背包的最大价值,状态转移方程就是 dp[i][j]
= max(dp[i - 1][j], dp[i-1][j - w[i]] + v[i]), 这个式子的意思想必大家都明白吧,前面的那个意思是不取当前这个,后面的这个是取上当前这个物品, 后来再经空间优化之后变成了dp[j] = max(dp[j], dp[j - w[i]] + v[i]), 仔细观察会发现二维数组时,那两种状态都是i - 1,所以就可以去掉,但是得注意,循环遍历的时候要逆序,正序的话就成完全背包了, 忘了说这个dp[j]表示什么了, dp[j]就是 当取到重量为j 的时候的最大价值。弄明白了这些。这时候就可以来看这个题了,
题目要求和普通的01背包一样,求能装的最大价值,普通方法就是直接找最大价值,现在要换种思维,找最小的重量, 因为同样价值,重量越小,那么最后能装的价值就可能越大,所以这个dp[i][j]就表示 当 取 i 个, 价值为j 的时候的最小重量,状态转移方程为 dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]), 和那个最初推的一样,不再罗嗦,空间优化之后状态转移方程为dp[j] = min(dp[j], dp[j - v[i]] + w[i]), 同样的意思,dp[j]表示
价值为j 的时候的最小重量,到最后只要从最大价值往下遍历这个dp数组,只要找到dp[j] <= 背包重量的时候就直接输出 j , 这时候j就是最大的。
AC代码:
有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W
的物品,求所有挑选方案中物品价值总和的最大值。
1 <= n <=100
1 <= wi <= 10^7
1 <= vi <= 100
1 <= W <= 10^9
输入多组测试数据。
每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。
输出满足题意的最大价值,每组测试数据占一行。
样例输入
4 5 2 3 1 2 3 4 2 2
样例输出
7
分析:这道题其实和一般的01背包没有什么区别,只是这道题目按照正常的思维去做不行了,因为容量太大,开个10^9的数组开不了,所以这时候就需要换种思维。
这道题很容易发现其实重量很大,达到10^9,但是价值很小啊,现在就来推一下这个所谓的“互换”是怎么来的 (其实我觉得还不如从最原始的来,不叫做“互换”好理解点), 最原始的那个式子dp[i][j]表示当取 i 个, 重量为 j 的时候背包的最大价值,状态转移方程就是 dp[i][j]
= max(dp[i - 1][j], dp[i-1][j - w[i]] + v[i]), 这个式子的意思想必大家都明白吧,前面的那个意思是不取当前这个,后面的这个是取上当前这个物品, 后来再经空间优化之后变成了dp[j] = max(dp[j], dp[j - w[i]] + v[i]), 仔细观察会发现二维数组时,那两种状态都是i - 1,所以就可以去掉,但是得注意,循环遍历的时候要逆序,正序的话就成完全背包了, 忘了说这个dp[j]表示什么了, dp[j]就是 当取到重量为j 的时候的最大价值。弄明白了这些。这时候就可以来看这个题了,
题目要求和普通的01背包一样,求能装的最大价值,普通方法就是直接找最大价值,现在要换种思维,找最小的重量, 因为同样价值,重量越小,那么最后能装的价值就可能越大,所以这个dp[i][j]就表示 当 取 i 个, 价值为j 的时候的最小重量,状态转移方程为 dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]), 和那个最初推的一样,不再罗嗦,空间优化之后状态转移方程为dp[j] = min(dp[j], dp[j - v[i]] + w[i]), 同样的意思,dp[j]表示
价值为j 的时候的最小重量,到最后只要从最大价值往下遍历这个dp数组,只要找到dp[j] <= 背包重量的时候就直接输出 j , 这时候j就是最大的。
AC代码:
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; int dp[10000]; int w[110],v[110]; int main() { int n,m,i,j; while(~scanf("%d%d",&n,&m)) { memset(dp,0x3f,sizeof(dp)); dp[0]=0; int sum=0; for(i=0; i<n; i++) { scanf("%d %d",&w[i],&v[i]); sum+=v[i]; } for(i=0; i<n; i++) for(j=sum; j>=v[i]; j--) { dp[j]=min(dp[j],dp[j-v[i]]+w[i]); } for(i=sum;i>=0;i--) if(dp[i]<=m) { printf("%d\n",i); break; } } return 0; }
相关文章推荐
- 高斯图像滤波原理及其编程离散化实现方法
- memcache简介以及使用方法
- 斜率dp
- 20.从上往下打印二叉树
- excel中以文本形式保存长数字
- 错误检查
- 面向对象五大原则之一:单一职责原则
- 搭建ARM DS-5 STREAMLINE
- Getting Spring Error “Bean named 'x' must be of type [y], but was actually of type [$Proxy]” in Jenk
- POJ 2255 Tree Recovery && Ulm Local 1997 Tree Recovery (二叉树的前中后序遍历)
- Reddit网站获赞最高文章/评论的爬取
- ZOJ 3869-Ace of Aces【模拟众数】
- 【深入理解JVM】:Class类文件结构
- 10474 - Where is the Marble?
- STM32_外部中断(寄存器版)_笔记
- 进制转换
- HDOJ(HDU) 2192 MagicBuilding(用Java的Map做了下)
- cmd命令大全
- ajax
- Hibernate自动生成的DAO的修改方法