算法学习:01背包(动规)

算法学习: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背包,没有考虑空间的使用等等,只是实现了完整的动规的想法。
写完这个代码,感觉好像对于算法导论上的一句话有些明白了,分治法是要把一个问题分解成许多的子问题,子问题之间是没有重叠的,动规也是在把问题化小,但是如果用递归实现的话,就会解很多重复的子问题。所以最好用自底向上的思想来解题,记录计算过的子问题,再用到的时候就直接去查找就可以了。
背包还是要进一步学习的,以后继续更新~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值