算法学习:01背包
贪心之后来动规啦~看《算法导论》感觉还是不那么清楚,还是得自己动手才行~真正写的时候发现还是没有真正理解动规的自底向上的求解方法,又看了几篇博文,才初步了解了01背包的真正的执行过程。
必须推荐一下参考的文章,也记录一下,以便日后进一步学习:
http://blog.csdn.net/sj13051180/article/details/6687674
http://blog.csdn.net/dapengbusi/article/details/7463968
http://blog.csdn.net/liufeng_king/article/details/8683136
不说了,上代码:
/*
0-1背包问题
*/
#include<iostream>
using namespace std;
const int c = 5;//背包最大容量
const int n = 3;//待装入物品总数量
int weight[n+1] = {0, 1, 2, 3};
int value[n+1] = {0, 60, 100, 120};
int main()
{
int m[n+1][c+1]={0};//动规的重点,记录最优子结构的内容
//memset(m, 0, sizeof(m));//初始化为0
//想写一个函数来实现,突然发现不会二维数组参数传递
//先写在主函数中吧,回头学会了再完善~~
//自顶向下的顺序
//首先放置第一个物品
for(int j = 0; j <= c; j++)
{
if(j >= weight[1])
{
m[1][j] = value[1];
}
}
for(int i = 2; i <= n; i++)
{
for(int j = 0; j <= c; j++)
{
if(j >= weight[i])
{
int temp = m[i-1][j-weight[i]] + value[i];//i放进背包
if(m[i-1][j] < temp)
{
m[i][j] = temp;
}else{
m[i][j] = m[i-1][j];
}
}
else
{
m[i][j] = m[i-1][j];
}
}
}
int x[n+1]={0};//回溯找到放了哪几个物品
int tempc = c;
for(int i = n; i >= 1; i--)
{
if(m[i][tempc] != m[i-1][tempc])
{
x[i] = 1;
tempc -= weight[i];
}
else
{
x[i] = 0;
}
}
cout << "选中的物品为:" << endl;
for(int i = 1; i <= n; i++)
{
if(x[i])
{
cout << i << endl;
}
}
return 0;
}
上面写的是一个最简单的01背包,没有考虑空间的使用等等,只是实现了完整的动规的想法。
写完这个代码,感觉好像对于算法导论上的一句话有些明白了,分治法是要把一个问题分解成许多的子问题,子问题之间是没有重叠的,动规也是在把问题化小,但是如果用递归实现的话,就会解很多重复的子问题。所以最好用自底向上的思想来解题,记录计算过的子问题,再用到的时候就直接去查找就可以了。
背包还是要进一步学习的,以后继续更新~