您的位置:首页 > 其它

简单01背包问题 一维解决方法

2011-11-28 19:50 337 查看
首先简单01背包问题:

N种物品  每种只有一个 给出每个的体积w和价值h

再给出背包的体积V、

问能装入物品的最大总价值是多少

问题的最后分为两种情况 一是必须刚好物品总体积是V  二是不要求恰好 只求最大价值 在最后会对两种情况区分、

每种物品只有一个 所以问题结果就是每个物品装包或舍弃的状态、

状态转移方程为:f[i][v] = max( f[i-1][v] , f[i-1][v-w[i]]+h[i] )

算法代码为:

for(i=1;i<=n;i++)
for(j=v;j>=0;j--)
if(j>=w[i])
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+h[i])


max中两个值的意思分别是 若第i个物品丢弃的总价值为前i-1个物品装入体积为V的背包中的价值 若第i个物品装包的总价值为前i-1个物品装入体积为V-w[i] 的背包中的总价值、

这个方法是二维的  空间上可以优化为一维的  因为f[i]是只由f[i-1]推导出的  j倒序遍历即可实现一维

既:

for(i=1;i<=n;i++)
for(j=v;j>=0;j--)
if(j>=w[i])
f[j]=max(f[j],f[j-w[i]]+h[i]);


再说刚才提的是否恰好装满的问题、

对于两种不同的情况 只需在f数组初始化的时候进行区别即可

恰好时讲f[0]赋值为0  其他赋值为负无穷  意思是若不装入物品 只有当背包的体积为0时才满足“恰好”的条件  其他情况不满足、

不要求恰好时  就将f所有都赋值为0、

poj3624  典型01背包   不要求恰好装满  代码如下:

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int num,j,zw,w[3500],v[3500],f[12890];
memset(f,0,sizeof(f));
cin>>num>>zw;
for(int i=0;i<num;i++)
{
cin>>w[i]>>v[i];
}
for(int i=0;i<num;i++)
{
for(j=zw;j>=0;j--)
{
if(j-w[i]>=0)
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
}
cout<<f[zw]<<endl;
}
AC
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 优化