poj3624----01bag(一维+(二维+滚动数组))
来源:互联网 发布:山东招宝万金网络 编辑:程序博客网 时间:2024/06/07 00:25
Description
Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a 'desirability' factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).
Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di
Output
* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints
Sample Input
4 61 42 63 122 7
Sample Output
23
题意:一共量为N块宝石,想要镶嵌最多W的重量的宝石
下面给出在重量为W宝石,镶嵌相应宝石会得到相应宝石的魔法为D
一维dp的循环里面开始点和二维的不同
二维01 dp + 滚动数组
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int weight[4000],value[4000];int dp[3][13000];int main(){ int n,m; //freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d%d",&weight[i],&value[i]); for(int i=0;i<n;i++) for(int j=0;j<=m;j++) if(j>=weight[i]) dp[(i+1)%2][j]=max(dp[i%2][j],dp[i%2][j-weight[i]]+value[i]); else dp[(i+1)%2][j]=dp[i%2][j]; printf("%d\n",dp[n%2][m]); return 0;}
其中第二层循环可以是
for(int j=m;j>=0;j--)
并且两层循环不可以互换
一维01dp
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int a[40000][3];int dp[40000];int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d%d",&a[i][0],&a[i][1]); for(int i=0;i<n;i++) for(int j=m;j>=a[i][0];j--) dp[j]=max(dp[j],dp[j-a[i][0]]+a[i][1]); printf("%d\n",dp[m]); return 0;}
如何理解二维降一维呢?
对于外层循环中的每一个i值,其实都是不需要记录的,在第i次循环时,所有的dp[0…v]都还未更新时,dp[j]还记录着前i-1个物品在容量为j时的最大价值,这样就相当于还记录着dp[i-1][j]和dp[i-1][j-vol[i]]+val[i]。
为什么要从v开始递减遍历?
我举个例子,假设一个物品GG价值1000,体积为2,那么假设我们按【0…..v】这个顺序遍历,那么在j=2时,dp[2] = max(dp[2], dp[0]+1000),那么dp[2] = 1000,当j=4时,dp[4]=max(dp[4], dp[2]+1000), dp[4] = 2000,这时我们再思考一下,GG将被放进背包两次!!,如果我们逆序遍历,就可以避免这种结果。
初始化的细节问题
我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。有的题目要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。一种区别这两种问法的实现方法是在初始化的时候有所不同。
如果是第一种问法,要求恰好装满背包(推荐blog :http://blog.csdn.net/summer__show_/article/details/51447328),那么在初始化时除了f[0]为0其它f[1..V]均设为正无穷负无穷,这样就可以保证最终得到的f[N]是一种恰好装满背包的最优解。
如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将f[0..V]全部设为0。
为什么呢?可以这样理解:初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。
- poj3624----01bag(一维+(二维+滚动数组))
- POJ3624---01背包入门 dp+滚动数组+重复利用一维数组
- HDU 2602 Bone Collector(01二维背包&一维背包&滚动数组优化二维背包的原理 )
- POJ3624 Charm Bracelet 01背包 一维数组表示
- 知识点:01背包(多种姿势:二维实现+一维实现+滚动数组实现+背包装满+输出最优方案)
- POJ-2019(二维RMQ + 滚动数组)
- Smarty遍历数组 (一维、二维)
- 树状数组(一维、二维)入门
- JAVA数组(一维与二维):
- 树状数组(一维&&二维)
- java入门--数组(一维数组和二维数组)
- 折腾二维数组(一)
- C语言指针与二维数组(二维数组与一维数组关系)
- 数组---(一维、二维数组,求最值,排序)
- 一维数组变二维数组的写法(详解)
- C# 一维数组、二维数组(矩形数组)、交错数组(锯齿数组)的使用
- NYOJ 289 苹果(01背包)两种解法,二维数组,一维数组
- 一维数组、二维数组
- poj2389 大整数乘法
- 多式子递推poj2545 poj2591 poj1338
- 素数筛选法 poj1164
- 下拉控价Spinner的使用
- poj1001 经典大整数
- poj3624----01bag(一维+(二维+滚动数组))
- poj3158 同时向前运行的处理模板
- poj 3257 二维dp
- poj 3211 结构体-分组一维dp
- poj 2385 经典dp
- poj3461 KMP
- KMP 模板
- mono 安装 -2016/2/1
- poj 2752 KMPnext[]数组的理解 以及 两种优化