在动态规划中,有一类经常出现的问题,即0-1背包问题。所谓0-1背包问题,即有n个物品,其每个背包的价值为vi(1<=i<=n),每个物品的重量为wi(1<=i<=n),背包能够放的总重量为c,求放哪几个物品使得物品的总价值最大。
很明显,物品要么放进背包,要么不放进。故称为0-1背包。
我们假设放进了m个物品{x1,x2,...,xm},那么它是满足最优子结构的,即如果这是问题的最优解,那么{x2,...,xm}一定是问题c-wx1的最优解。所以,这道问题可以用动态规划进行求解。
我们可以定义一个数组m[i][j],用它表示背包容量为j,可选物品为i,i+1,...,n时背包问题的最优值。那么我们可以推断出:
当wi>j时,m[i][j]=m[i+1][j],当wi<=j时,m[i][j]=max{m[i+1][j],m[i+1][j-wi]+vi}。
所以求解背包问题的代码如下:
很明显,物品要么放进背包,要么不放进。故称为0-1背包。
我们假设放进了m个物品{x1,x2,...,xm},那么它是满足最优子结构的,即如果这是问题的最优解,那么{x2,...,xm}一定是问题c-wx1的最优解。所以,这道问题可以用动态规划进行求解。
我们可以定义一个数组m[i][j],用它表示背包容量为j,可选物品为i,i+1,...,n时背包问题的最优值。那么我们可以推断出:
当wi>j时,m[i][j]=m[i+1][j],当wi<=j时,m[i][j]=max{m[i+1][j],m[i+1][j-wi]+vi}。
所以求解背包问题的代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int n;
//计算
void cal(int *v,int *w,int c,int m[6][11]){
int jMax = min(w[n-1]-1,c);
//首先判断第n个
for(int j=0;j<=jMax;j++)
m[n][j] = 0;
for(int j=w[n-1];j<=c;j++)
m[n][j] = v[n-1];
//在判断2~n
for(int i=n-1;i>=1;i--) {
jMax = min(w[i-1]-1,c);
for(int j=0;j<=jMax;j++)
m[i][j] = m[i+1][j];
for(int j=w[i-1];j<=c;j++)
m[i][j] = max(m[i+1][j],m[i+1][j-w[i-1]]+v[i-1]);
}
bool tag[6];
for(int i=n;i>=1;i--){
if(m[i][c]!=0){
tag[i]=true;
c=c-w[i];
} else{
tag[i]=false;
}
}
for(int i=1;i<=n;i++){
if(tag[i]){
cout<<i<<" ";
}
}
}
//背包问题
int main() {
n=5;
int c=10;
int w[5] = {2,2,6,5,4};
int v[5] = {6,3,5,4,6};
int m[6][11];
cal(v,w,c,m);
cout<<endl;
system("pause");
return 0;
}