您的位置:首页 > 其它

背包九讲-01背包

2013-06-16 16:42 302 查看
tianyi cui 的背包九讲老版本:http://love-oriented.com/pack/

更新后的版本PDF下载:http://cuitianyi.com/blog/%E3%80%8A%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98%E4%B9%9D%E8%AE%B2%E3%80%8B2-0-alpha1/

新版pdf下载地址2:http://download.csdn.net/detail/tangzhangpeng/5591321

本文实现了新版本第一章 “01背包问题”,代码中的注释也是针对新版本。

pdf 1.5 小节中的小错误,常数优化应该是

#include<iostream>
#include<string>
#include<vector>
using namespace std;

inline int max(int a, int b)
{
return a>b?a:b;
}

int ZeroOnePack1(int n, int v, int c[], int w[], bool needFull)
{
//根据tianyi cui背包九讲1.2的最原始的解法
//时间空间复杂度均为O(nv)
// n 物品数量
// v 背包容量
// c[] 物品耗费的空间,从c[1]开始
// w[] 物品的价值,从w[1]开始
// needFull 背包是否需要完全装满
const int MIN = numeric_limits<int>::min(); //表示负无穷
int **f = new int*[n+1];
for(int i = 0; i < n+1; i++)
f[i] = new int[v+1];
if(needFull)  //初始化细节详见 背包九讲1.4
{
for(int i = 0; i <= n; i++)
for(int j = 0; j <= v; j++)
f[i][j] = MIN;
f[0][0] = 0;
}
else
{
for(int i = 0; i <= n; i++)
for(int j = 0; j <= v; j++)
f[i][j] = 0;
}

for(int i = 1; i <= n; i++)
for(int j = c[i]; j <= v; j++)
{
f[i][j] = max(f[i - 1][j], f[i - 1][j - c[i]] + w[i]);
}
if(f
[v] < 0)return -1;  //针对背包装满的情况,没有满足的答案
return f
[v];
}

int ZeroOnePack2(int n, int v, int c[], int w[], bool needFull)
{
//根据tianyi cui背包九讲1.3在1.2的基础上优化空间复杂度后的解法
//时间复杂度均为O(nv),空间复杂度为O(v)
// n 物品数量
// v 背包容量
// c[] 物品耗费的空间,从c[1]开始
// w[] 物品的价值,从w[1]开始
// needFull 背包是否需要完全装满
const int MIN = numeric_limits<int>::min(); //表示负无穷
int *f = new int[v+1];
if(needFull)  //初始化细节详见 背包九讲1.4
{
for(int i = 0; i <= v; i++)
f[i] = MIN;
f[0] = 0;
}
else
{
for(int i = 0; i <= v; i++)
f[i] = 0;
}

for(int i = 1; i <= n; i++)
for(int j = v; j >= c[i]; j--)
{
f[j] = max(f[j], f[j - c[i]] + w[i]);
}
if(f[v] < 0)return -1;  //针对背包装满的情况,没有满足的答案
return f[v];
}

int ZeroOnePack3(int n, int v, int c[], int w[], bool needFull)
{
//根据tianyi cui背包九讲1.5,在1.3的基础上有个常数的优化,在v较大时,有明显优势
//时间复杂度均为O(nv),空间复杂度为O(v)
// n 物品数量
// v 背包容量
// c[] 物品耗费的空间,从c[1]开始
// w[] 物品的价值,从w[1]开始
// needFull 背包是否需要完全装满
const int MIN = numeric_limits<int>::min(); //表示负无穷
int *f = new int[v+1];
if(needFull)  //初始化细节详见 背包九讲1.4
{
for(int i = 0; i <= v; i++)
f[i] = MIN;
f[0] = 0;
}
else
{
for(int i = 0; i <= v; i++)
f[i] = 0;
}

int csum = 0;
c[0] = 0;
for(int i = 1; i <= n; i++)csum += c[i];
for(int i = 1; i <= n; i++)
{
csum -= c[i-1];
for(int j = v; j >= max(c[i], v - csum); j--)
{
f[j] = max(f[j], f[j - c[i]] + w[i]);
}
}
if(f[v] < 0)return -1;  //针对背包装满的情况,没有满足的答案
return f[v];
}

int main()
{
//87
int c[] = {0,2,7,3,4,8,5,8,6,4,16};
int w[] = {0,15,25,8,9,15,9,13,9,6,14};
int result = ZeroOnePack3(10, 34, c, w, true);
cout<< result <<endl;

//82
int c1[] = {0,4,5,7,2,8,3,6,1,10,9};
int w1[] = {0,25,14,15,4,14,5,8,1,10,2};
int result1 = ZeroOnePack3(10, 34, c1, w1, true);
cout<< result1 <<endl;

//-1
int c2[] = {0,2,3,6};
int w2[] = {0,15,10,16};
int result2 = ZeroOnePack3(3, 10, c2, w2, true);
cout<< result2 <<endl;

//85
int c3[] = {0,2,8,4,4,8,7,8,5,16,16};
int w3[] = {0,15,25,9,9,15,12,12,6,14,9};
int result3 = ZeroOnePack3(10, 34, c3, w3, true);
cout<< result3 <<endl;

//83
int c4[] = {0,4,5,7,2,8,3,9,6,1,10};
int w4[] = {0,25,14,15,4,14,5,14,8,1,10};
int result4 = ZeroOnePack3(10, 34, c4, w4, true);
cout<< result4 <<endl;
}


View Code
【版权声明】转载请注明出处 /article/4879603.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: