0-1背包问题(动态规划)
来源:互联网 发布:dragonframe mac 破解 编辑:程序博客网 时间:2024/05/13 18:26
一 问题描述:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
所谓01背包,表示每一个物品只有一个,要么装入,要么不装入。
二 解决方案:
考虑使用动态规划求解,定义一个递归式 opt[i][v] 表示前i个物品,在背包容量大小为v的情况下,最大的装载量。
opt[i][v] = max(opt[i-1][v] , opt[i-1][v-c[i]] + w[i])
解释如下:
opt[i-1][v] 表示第i件物品不装入背包中,而opt[i-1][v-c[i]] + w[i] 表示第i件物品装入背包中。
花费如下:
时间复杂度为O(V * N) ,空间复杂度为O(V * N)。时间复杂度已经无法优化,但是空间复杂度则可以进行优化。
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
所谓01背包,表示每一个物品只有一个,要么装入,要么不装入。
二 解决方案:
考虑使用动态规划求解,定义一个递归式 opt[i][v] 表示前i个物品,在背包容量大小为v的情况下,最大的装载量。
opt[i][v] = max(opt[i-1][v] , opt[i-1][v-c[i]] + w[i])
解释如下:
opt[i-1][v] 表示第i件物品不装入背包中,而opt[i-1][v-c[i]] + w[i] 表示第i件物品装入背包中。
花费如下:
时间复杂度为O(V * N) ,空间复杂度为O(V * N)。时间复杂度已经无法优化,但是空间复杂度则可以进行优化。
但必须将V 递减的方式进行遍历,即V.......0 的方式进行(其实可以V....c[i])。
knapsack:
1:只装入1个物品,确定在各种不同载重量的背包下,能够得到的最大价值
2:装入2个物品,确定在各种不同载重量的背包下,能够得到的最大价值
。。。
n:以此类推,装入n个物品,确定在各种不同载重量的背包下,能够得到的最大价值
printMaxValue:
确定装入背包的具体物品,从opt[n][m]向前逆推:
若opt[n][m]>opt[n-1][m],则第n个物品被装入背包,且前n-1个物品被装入载重量为m-w[n]的背包中
否则,第n个物品没有装入背包,且前n-1个物品被装入载重量为m的背包中
以此类推,直到确定第一个物品是否被装入背包为止
使用二维数组opt求解:
#include<iostream>#define MAX 20#define max(a,b) a>b?a:b using namespace std;int N,V;//物品数量和容量int cost[MAX]; //费用int value[MAX]; //价值int opt[MAX][MAX]; //存放最大价值int x[MAX];//x[i]为1表示第i个物品放入背包int knapsack()//参数是物品数量和容量,X数组表示组成,F[N][V]表示最大价值{memset(opt,0,sizeof(opt));//初始化opt为0 for(int i=1;i<=N;i++)//求最大价值{for (int j=1;j<=V;j++){if (cost[i]<=j)opt[i][j]=max(value[i]+opt[i-1][j-cost[i]],opt[i-1][j]);else opt[i][j]=opt[i-1][j];}}return opt[N][V];//返回最大值}void printMaxValue()//输出opt中的值(本函数无实际作用,只是为了显示下数据){for(int i=0;i<=N;i++){for(int j=0;j<=V;j++)cout<<opt[i][j]<<" ";cout<<endl;}} void traceback()//输出放入背包的物品编号 {for(int i=N;i>0;i--)//x[i]为1表示第i个物品放入背包 {if(opt[i][V]==opt[i-1][V])x[i]=0;else{x[i]=1;V-=cost[i];}}for(int i=0;i<=N;i++)if(x[i]) cout<<i<<" ";}int main(){while(cin>>N>>V)//输入物品数量和背包容量 {for(int i=1;i<=N;i++)cin>>cost[i]>>value[i];cout<<"max="<<knapsack2()<<endl;printMaxValue();traceback();cout<<endl;}return 0;}
优化空间复杂度为O(V),使用一维数组:
#include<iostream>#define MAX 20using namespace std;int N,V;//物品数量和容量int cost[MAX]; //费用int value[MAX]; //价值int opt[MAX]; //存放价值int knapsack() //参数是物品数量和容量,X数组表示组成,F[N][V]表示最大价值{memset(opt,0,sizeof(opt));//初始化opt为0 for(int i=1;i<=N;i++)//求最大价值{for (int j=V;j>=cost[i];j--){if (value[i]+opt[j-cost[i]]>opt[j]) opt[j]=value[i]+opt[j-cost[i]];}}return opt[V];//返回最大值}int main(){while(cin>>N>>V)//输入物品数量和背包容量 {for(int i=1;i<=N;i++)cin>>cost[i]>>value[i];cout<<"max="<<knapsack()<<endl;}return 0;}
参考 http://www.cppblog.com/jake1036/archive/2011/06/27/149566.html
- 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背包问题
- Gentoo U盘安装
- hdu1541/poj2352 线段树之单点更新
- 大数阶乘
- ZOJ 1655 Transport Goods
- 分页技术
- 0-1背包问题(动态规划)
- Windows Workflow Foundation 4.0
- Session之我总结
- 线程
- CRC 在软件加密保护中的应用(转载)
- POJ1014 Dividing
- 单一职责原则?
- 从”零“开始
- Lua与C/C++的交互5:C/C++调用Lua函数