NYOJ860 又见01背包(01背包的另一种思路)
来源:互联网 发布:网络教育心理学 编辑:程序博客网 时间:2024/06/01 07:13
题目:
又见01背包
- 描述
- 有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W的物品,求所有挑选方案中物品价值总和的最大值。1 <= n <=1001 <= wi <= 10^71 <= vi <= 1001 <= W <= 10^9
- 输入
- 多组测试数据。
每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。 - 输出
- 满足题意的最大价值,每组测试数据占一行。
- 样例输入
4 52 31 23 42 2
- 样例输出
7
这道题很容易发现其实重量很大,达到10^9,但是价值很小啊,现在就来推一下这个所谓的“互换”是怎么来的(其实我觉得还不如从最原始的来,不叫做“互换”好理解点),最原始的那个式子
dp[i][j]表示当取 i个, 重量为 j的时候背包的最大价值,状态转移方程就是 dp[i][j] = max(dp[i - 1][j], dp[i-1][j - weight[i]] + value[i]), 这个式子的意思想必大家都明白吧,前面的那个意思是不取当前这个,后面的这个是取上当前这个物品, 后来再经空间优化之后变成了dp[j] = max(dp[j], dp[j - weight[i]] + value[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 - value[i]] + weight[i]),和那个最初推的一样,不再罗嗦,空间优化之后状态转移方程为dp[j] = min(dp[j], dp[j - value[i]] + weight[i]),同样的意思,dp[j]表示 价值为j的时候的最小重量,到最后只要从最大价值往下遍历这个dp数组,只要找到dp[j] <=背包重量的时候就直接输出 j, 这时候j就是最大的。
代码:
#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>#define mem(a,b) memset(a,b,sizeof(a))using namespace std;int weight[200],value[200];int dp[10005];int main(){ int n,w;//w表示最大的重量 while(~scanf("%d %d",&n,&w)) { int sum=0; for(int i=0; i<n; i++) { scanf("%d %d",&weight[i],&value[i]); sum+=value[i];//算出总价值 } mem(dp,0x3f);//初始化数组非常大 dp[0]=0; for(int i=0; i<n; i++) { for(int j=sum; j>=value[i]; j--) dp[j]=min(dp[j],dp[j-value[i]]+weight[i]);//dp[j]表示价值为j时候的最小重量 } for(int i=sum; i>=0; i--) { if(dp[i]<=w)//当当前的价值的最小重量小于等于题目需要的最大重量时,输出这时的价值i { printf("%d\n",i); break; } } } return 0;}
- NYOJ860 又见01背包(01背包的另一种思路)
- nyoj860又见01背包
- nyoj860又见01背包
- nyoj860又见01背包
- nyoj860 又见01背包
- nyoj860 又见01背包
- NYOJ860又见01背包
- NYOJ860 又见01背包
- nyoj860又见01背包
- NYOJ860:又见01背包(01背包入门2)
- nyoj860 又见01背包(背包变形)
- 背包问题——nyoj860 又见01背包
- nyoj860 01背包变形-好题
- 又见01背包。(另类的01背包问题)
- 背包问题:另一种思路
- 又见01背包
- 又见01背包
- 又见01背包
- Android Fragment
- Android 获取SHA1(发布版和调试版)
- Struts2的知识整理总结(一)
- web开发网页(一)
- 【预研】Storm C++ Wrapper demo的单机版本实现
- NYOJ860 又见01背包(01背包的另一种思路)
- 测试基础积累
- GCD dispatch_async 与dispatch_sync 的理解
- 自定义ViewGroup中onLayout()确定子View位置和大小
- Javascript Api
- redis字符串string类型的操作
- 项目部署之工具使用心得
- JSON.parse()和JSON.stringify()
- java:根据文件头来判断文件类型