【动态规划】0-1背包问题
来源:互联网 发布:股票虚拟盘软件 编辑:程序博客网 时间:2024/05/02 02:12
一、问题
有N件物品和一个容量(最大承重)为V的背包。第i件物品的体积(重量)是w[i],价值是p[i]。求解将哪些物品装入背包可使价值总和最大。
所谓01背包,表示每一个物品只有一个,要么装入,要么不装入。
二、分析
0-1背包属于求最优解,当然用动态规划解决,当然也可以用其他方法解决。这里介绍动态规划方法。
阶段是:在前N件物品中,选取若干件物品放入背包中;
状态是:在前N件物品中,选取若干件物品放入所剩空间为W的背包中的所能获得的最大价值;
决策是:第N件物品放或者不放;
dp[i][j]是:在前 i 件物品中选择若干件放在所剩空间为 j 的背包里所能获得的最大价值;
状态转移方程:
1. dp[i][j] = 0 where j=0 or i =0
2. dp[i][j] = dp[i-1][j] where j< w[i]
3. dp[i][j] = max{dp[i-1][j], dp[i-1][j-w[i]] + p[i]} where j >= w[i]
解释:第一种是第i件不放进去,这时所得价值为:f[i-1][v]
第二种是第i件放进去,这时所得价值为:f[i-1][v-c[i]]+w[i]
三、实现
void display(int N,int V, int w[],int p[],int *dp){#define dp(i,j) *(dp + (i)*(V+1) + (j)) int i=N,j=V; vector<int> vrst; while(i>0 && j>0) { if (dp(i,j) != dp(i-1,j)) { vrst.push_back(i); j = j - w[i-1]; } i--; } for(vector<int>::iterator iter = vrst.begin(); iter != vrst.end(); ++iter) { cout << *iter << " " ; }#undef dp}//n个物品,容量为V,w为体积,p为价值void pack_of_01(int N,int V,int w[],int p[]){ int i,j; int* dp = (int*)malloc(sizeof(int)*(N+1)*(V+1));#define dp(i,j) *(dp + (i)*(V+1) + (j)) memset(dp,0,sizeof(int)*(V+1)*(N+1)); for (i=1;i<=N;i++) { for(j=1;j<=V;j++) { dp(i,j) = dp(i-1,j); //注意此时的i对应w和p中的i-1,因为dp多加了一个0行0列 if (j >= w[i-1] && (dp(i-1,j-w[i-1]) + p[i-1]) > dp(i-1,j)) { dp(i,j) = dp(i-1,j-w[i-1]) + p[i-1]; } } } for (i=1;i<=N;i++) { for(j=1;j<=V;j++) { cout << dp(i,j) << " "; } cout << endl; } display(N,V,w,p,dp); free(dp);#undef dp}
测试代码:
int p[T] = {12 , 10 , 20, 15 }; int w[T] = {2 , 1 , 3 , 2 }; pack_of_01(4,5,w,p);
结果:
四、优化
自己想了一种优化方法,就是只要O(V)的空间,因为dp[i][j]总是找dp[i-1][j]或者dp[i-1][j-w[i]]。所以每次从后往前遍历,相当于二维数组从后往前,从上往下遍历。但是,这只能获得最优解,不能获得最优的那个几个背包。
代码如下:
int packof01(){ for(int i = 0 ; i <= V ;i++) //条件编译,表示背包可以不存储满 f[i] = 0 ; for(int i = 0 ; i < N ; i++) { for(int v = V ; v >= w[i] ;v--) //必须全部从V递减到0 { f[v] = max(f[v-w[i]] + p[i] , f[v]) ; //此f[v]实质上是表示的是i-1次之前的值。 } } return f[V] ; }
五、扩展
01背包(ZeroOnePack):
有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
完全背包(CompletePack):
有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
多重背包(MultiplePack):
有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
- 0/1背包问题动态规划详解
- 动态规划解0-1背包问题
- 0/1背包问题动态规划详解
- 动态规划 ------0-1背包问题
- 0/1背包问题动态规划详解
- 动态规划解决0-1背包问题
- 0/1背包问题动态规划详解
- 0-1背包问题--动态规划解法
- 动态规划解0-1背包问题
- 0-1背包问题动态规划
- 0-1背包问题,动态规划求解
- 动态规划解决0-1背包问题
- 0/1背包问题动态规划详解
- 动态规划---0-1背包问题
- 动态规划解决0-1背包问题
- 动态规划解0-1背包问题
- 0/1背包问题----动态规划实现
- 动态规划0—1背包问题
- POJ3080 Blue Jeans(kmp & 暴力)
- Gson解析工具类----解决某些手机Object两个属性引起的异常
- Unity协程(Coroutine)原理深入剖析
- leetcode 22:Generate Parentheses(15-10-9)
- 1011. World Cup Betting
- 【动态规划】0-1背包问题
- Ubuntu14.04中fcitx-rime中州韵输入法安装设置
- VC从文件全路径中获取文件名和扩展名方法
- 类装载器体系结构
- 操作系统——pv操作示例
- MYSQL -- case when用法
- 编写测试用例时用到黑盒测试的方法
- Java 和Java虚拟机的关系
- iOS判断手机是否有网的方法