您的位置:首页 > 其它

01背包问题分析

2015-09-03 19:59 225 查看
 “背包题目”的基本描述是:有一个背包,能盛放的物品总重量为S,设有N件物品,其重量分别为w1,w2,…,wn,希望从N件物品中选择若干物品,所选物品的重量之和恰能放进该背包,即所选物品的重量之和即是S。递归和非递归解法都能求得“背包题目”的一组解,试写出“背包题目”的非递归解法。

解法一:

最初思路就是动态规划,

动态规划求一组解,我们用f[i][j]用来表示前i件物品随意选择一些物品能够恰好装满容量为j的背包的可行性=1,不可行则为0,其中i指的是物品标号,j指的是背包的大小(0~S);如果j < v[i]:f[i][j] = f[i-1][j] ,表示第i个物品的重量已经超过最大重量j了,则结果变为了前i-1件物品能否恰好装入容量为j的背包的可行性即等于f[i-1][j];

如果j>=v[i],此时就可以选择装或者不装第i件物品了,如果装入,则它的可行性就变为了前i-1前物品是否能恰好装入j-vec[i]容量的背包中可行性了;选择不装,则它的可行性变为了前i-1物品能否恰好装入容量为j的背包中可行性了,两者有一个可行,表明前i件物品就能恰好装入容量为j的背包中。f[i][j] = f[i-1][j]||f[i-1][j-vec[i]]

初始化:f[i][0]=1(i=0,1,2,,..n) 其它的f[i][j]都等于0

找出最终的一组解,用回溯就可以了。如果存在可行解,那么f
[S]一定为1

主要公式为:



代码为:

#include<iostream>
#include<vector>
using namespace std;
vector<int> packageInteration(int weight[], int S,int n);
void main()
{
int n=5;
int weight[]={4,5,7,9,8};
int S=20;
vector<int>res;
res=packageInteration(weight,S,n);

}
vector<int> packageInteration(int weight[], int S,int n)
{
vector<vector<int>>f;
vector<int> temp(S+1,0);
for(int i=0;i<n+1;i++)
{
f.push_back(temp);
}
for(int i=0;i<n+1;i++)
f[i][0]=1;
for(int i=1;i<n+1;i++)
{
for(int j=1;j<S+1;j++)
{
if(j>=weight[i-1])
f[i][j]=(f[i-1][j]||f[i-1][j-weight[i-1]]);//注意!!!这里用的是i-1而不是i的原因是,我们物体重量的数组下标是从0开始的,f的0列和0行无意义,是从1开始的。所以差别对待。
else
f[i][j]=f[i-1][j];
}
}
int j=S;
vector<int> res;
for(int i=n;i>0;i--)
{
if(j>=weight[i-1])
{
if(f[i][j-weight[i-1]]==1)
{
res.push_back(i);
j=j-weight[i-1];
}
}
}
return res;
}
这种动态规划的详细分析在博客中有提及,区别是f[i][j]值由总价值变为可行性。http://blog.csdn.net/sinat_24520925/article/details/42920909

另外值得注意的是:

动态规划的前提是我们的物体重量数组是排序的(由小到大),如果是随机的,我们仿真发现会有问题!!!!这用动态规划关键方程也可解释,j是由小到大的,我们的总重量是增量增加的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: