之前在做一个公司的面试题时候,遇到过背包问题。我当时想都没有想直接跳过了。
最近一直再刷动态规划的题目,终于是刷到了这个题目。
题目介绍:
lintcode92:背包问题
在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]。
例如:
如果有4个物品[2, 3, 5, 7]
如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。
如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。
函数需要返回最多能装满的空间大小。
这个题目想了很久,思路是有一点点,代码实现却困难重重。
我的思路是设计一个bool v[m][A.size()]的数组,其中m表示背包的大小,A.size(),表示物品的集合。如果在背包大小为m的情况下,A.at(i)这个物品放置则为true,否则就是假。
还设置一个num[m],表示背包大小为m时可以放置东西的个数。(没有考虑都题意)
在思考了差不多有一个小时之后,我选择搜索一下思路。动态规划题目做了差不多快10个,几乎没有一个题目有着清晰的思路。
正确的思路:
设置一个容器bool v[m+1];v[i]表示是否可以放置i重量的物品。
初始化条件 v[0] = true; //一定可以放置0重量的物品。
最优子结构 v[i] = v[i] || v[i - A.at(j)]; //其中j从0-A.size();
循环条件:最顶层的循环从0-A.size(),底层循环从m-A.at(i);从高到底。
最后的结果:从v[m]向前寻找。
总结:
动态规划解决问题的步骤很好掌握,不过确定最优子结构这个过程十分的难。多多积累,总会遇到有思路的。
代码如下:
class Solution { public: int backPack(int x, vector<int> &A) { bool v[x+1]; //初始化数据 v[0] = true; for(int i = 1; i < x+1 ; i++) { v[i] = false; } //循环 for(int i = 0 ; i < A.size() ; i++) { for(int j = x ; j >= A.at(i);j--) { v[j] = v[j] || v[j-A.at(i)]; } } for(int i = x ; i > 0 ;i--) { if(v[i]) { return i; } } //return 0; } };