背包问题,动态规划求解,matlab代码,c++代码
2016-09-08 16:42
751 查看
最近写论文接触到背包问题,查阅网上一些资料,对于简单的背包问题,动态规划算法可以求解,最近花时间整理整理。
背包问题描述:
有编号分别为a,b,c,d,e 的五件物品,它们的重量分别是 2,2,6,5,4,它们的价值分别是 6,3,5,4,6,现在给你个承重为 10 的背包,如何让背包里装入的物品具有最大的价值总和? (假设每类物品可以装多个)
根据求解动态规划问题的步骤,一步一步来。用 ci 表示各物品的重量,vi 表示各物品的价值。
阶段:
\begin{equation}i=1,2,\dots,5\end{equation}
第 i 阶段表示检查第 i 个物品。
状态变量:
\begin{equation}S_{i}\qquad i=1,2,\dots,5\end{equation}
表示检查第 i 个物品时包中的剩余承重量。一个问题能够用动态规划算法求解,必须保证状态空间是有限的。
决策变量:
\begin{equation}x_{i}\qquad i=1,2,\dots,5\end{equation}
表示第 i 个物品装入几个。
状态转移方程:
\begin{equation}S_{i+1}=S_{i}-c_{i}x_{i}\end{equation}
最优收益函数:
\begin{equation}\mathop{f}(S_{i})\end{equation}
表示检查第 i 个物品时,当包中剩余承重为 Si,包中装入物品 i, i+1, ... 5 能达到的最大价值。
最优收益函数转移方程:
\begin{equation}\mathop{f}\limits_{c_{i}x_{i}\leq S_{i}}(S_{i})= \begin{cases} v_{i}x_{i}+f(S_{i+1})\quad &i=1,2,\dots 4\\ v_{i}x_{i}\quad &i=5 \end{cases}\end{equation}
得到最优转移方程时,就可以求解了。从上式可以看出要用逆推法求解。当然也可以用顺推法求解,不过需要改变最优收益函数的定义。
动态规划求解时,都可以用矩阵来递推。
用了一位的前辈的图: http://blog.csdn.net/mu399/article/details/7722810。 我稍微改了下,不是0-1 背包,每类物品可以装多个。
这个图画的真不错!只是少了一列,s=0 的一列。
最优解是装入 5 个物品 a !
matlab 代码:
输出结果:
optimal solution:30
put 5 item1 in the bag
put 0 item2 in the bag
put 0 item3 in the bag
put 0 item4 in the bag
put 0 item5 in the bag
c ++ 代码:
用到了动态数组,以及能够返回一个数组的函数。
背包问题描述:
有编号分别为a,b,c,d,e 的五件物品,它们的重量分别是 2,2,6,5,4,它们的价值分别是 6,3,5,4,6,现在给你个承重为 10 的背包,如何让背包里装入的物品具有最大的价值总和? (假设每类物品可以装多个)
根据求解动态规划问题的步骤,一步一步来。用 ci 表示各物品的重量,vi 表示各物品的价值。
阶段:
\begin{equation}i=1,2,\dots,5\end{equation}
第 i 阶段表示检查第 i 个物品。
状态变量:
\begin{equation}S_{i}\qquad i=1,2,\dots,5\end{equation}
表示检查第 i 个物品时包中的剩余承重量。一个问题能够用动态规划算法求解,必须保证状态空间是有限的。
决策变量:
\begin{equation}x_{i}\qquad i=1,2,\dots,5\end{equation}
表示第 i 个物品装入几个。
状态转移方程:
\begin{equation}S_{i+1}=S_{i}-c_{i}x_{i}\end{equation}
最优收益函数:
\begin{equation}\mathop{f}(S_{i})\end{equation}
表示检查第 i 个物品时,当包中剩余承重为 Si,包中装入物品 i, i+1, ... 5 能达到的最大价值。
最优收益函数转移方程:
\begin{equation}\mathop{f}\limits_{c_{i}x_{i}\leq S_{i}}(S_{i})= \begin{cases} v_{i}x_{i}+f(S_{i+1})\quad &i=1,2,\dots 4\\ v_{i}x_{i}\quad &i=5 \end{cases}\end{equation}
得到最优转移方程时,就可以求解了。从上式可以看出要用逆推法求解。当然也可以用顺推法求解,不过需要改变最优收益函数的定义。
动态规划求解时,都可以用矩阵来递推。
用了一位的前辈的图: http://blog.csdn.net/mu399/article/details/7722810。 我稍微改了下,不是0-1 背包,每类物品可以装多个。
这个图画的真不错!只是少了一列,s=0 的一列。
name | weight | value | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
a | 2 | 6 | 0 | 6 | 6 | 12 | 12 | 18 | 18 | 24 | 24 | 30 |
b | 2 | 3 | 0 | 3 | 3 | 6 | 6 | 9 | 9 | 12 | 12 | 15 |
c | 6 | 5 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 12 | 12 | 12 |
d | 5 | 4 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 12 | 12 | 12 |
e | 4 | 6 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 12 | 12 | 12 |
matlab 代码:
function Knapsack c=[2 2 6 5 4];v=[6 3 5 4 6]; f=zeros(5,11);x=zeros(5,11);xx=zeros(5,1); for i=5:-1:1 for S=0:10 if i==5 f(i,S+1)=v(i)*floor(S/c(i)); x(i,S+1)=floor(S/c(i)); else xMax=floor(S/c(i)); ff=zeros(xMax+1,1); for k=0:xMax ff(k+1)=v(i)*k+f(i+1,S-c(i)*k+1); end [f(i,S+1),index]=max(ff); x(i,S+1)=index-1; end end end [optValue,index]=max(f(1,:)); xx(1)=x(1,index); tempS=index; fprintf('optimal solution:%d\n',optValue); for i=2:5 xx(i)=x(i,tempS-c(i-1)*xx(i-1)); tempS=tempS-c(i-1)*xx(i-1); end for i=1:5 fprintf('put %d item%d in the bag\n',xx(i),i); end end
输出结果:
optimal solution:30
put 5 item1 in the bag
put 0 item2 in the bag
put 0 item3 in the bag
put 0 item4 in the bag
put 0 item5 in the bag
c ++ 代码:
用到了动态数组,以及能够返回一个数组的函数。
#include"stdio.h" #include"stdlib.h" int * Max(int *arr, int n) { int *a=(int *)malloc(2*sizeof(int)); a[0]=0;a[1]=0; for (int i=0;i<n;i++) { if (arr[i]>a[0]) { a[0]=arr[i];a[1]=i; } } return a; } void main() { static const int c[5]={2,2,6,5,4}; static const int v[5]={6,3,5,4,6}; int f[5][11]; int x[5][11]; int itemNum[5]; for (int i=5;i>0;i--) for (int S=0;S<11;S++) { if (i==5) { f[i-1][S]=v[i-1]*(S/c[i-1]); x[i-1][S]=S/c[i-1]; } else { int xMax=S/c[i-1]; int * ff= (int *)malloc(sizeof(int)*(xMax+1)); for(int k=0;k<=xMax;++k) ff[k]=v[i-1]*k+f[i][S-c[i-1]*k]; int *a=Max(ff,xMax+1); f[i-1][S]=a[0];x[i-1][S]=a[1]; free(a); free(ff); } } int *temp=f[0]; int *maxValue=Max(temp,11); int tempS=maxValue[1]; itemNum[0]=x[0][tempS]; for (int i=1;i<5;++i) { itemNum[i]=x[i][tempS-c[i-1]*itemNum[i-1]]; tempS-=c[i-1]*itemNum[i-1]; } printf("the optimal solution is: %d\n",maxValue[0]); for(int i=0;i<5;i++) printf("put %d item%d in the bag\n",itemNum[i],i+1); free(maxValue); }
相关文章推荐
- 用贪心算法求解普通背包问题的C++代码
- Matlab遗传算法优化问题求解的演示样例代码
- 最大子数组问题-暴力求解-c++代码实现及运行实例结果
- 数值计算方法 求解初值问题(伪代码 c/c++ python)
- 用c++代码实现贪心算法求解最短路径问题
- 最简单的0-1背包问题c++代码实例及运行结果
- 最大子数组问题-暴力求解-c++代码实现及运行实例结果
- 所有背包问题代码总结 C++
- 0-1背包问题及其动态规划求解之二——王晓东的书本解法
- 动态规划求解01背包相关的基本问题
- 最大子数组问题-暴力求解-c++代码实现及运行实例结果
- 《算法导论》读书笔记之第16章 0-1背包问题—动态规划求解
- 遗传算法 求解旅行商 TSP 问题,matlab代码
- 动态规划求解背包问题(java版本)
- 0-1背包问题蛮力法求解(c++版本)
- 《算法导论》读书笔记之第16章 0-1背包问题—动态规划求解
- 最大子数组问题-暴力求解-c++代码实现及运行实例结果
- 背包问题求解Java代码
- Java 动态规划求解0-1背包问题
- 0-1背包问题与完全背包问题C++实现 动态规划