自古肉番出燃曲.......阿类,K-on为毛被算肉番了.......肉就肉吧,人妻忧嫁我就好了......
好像又扯远了......
近几天,已经陆续好几个公司召开了宣讲会,貌似有些公司都面试了......今天下午本来是TCL的宣讲,不过在那之前我去了一趟中国邮政,把签完的offer邮寄回去了- -0,我就是要去捣乱,怎么的,有本事咬我啊......
其实,本来不打算更新了,因为感觉中国的公司,会问及比较深算法的米有......只要你把本博客前面的文章都看过了,面试算法题可以all-kill了,当然,我知道很多人不会看.....
哦,好像还没有说今天的主题......恩,就是动态规划(DP)......为什么打算更新了呢,还是那句话,多学一点没坏处,而且,去年google笔试,7道题里有2道都是DP的,当然,如果你想去google,看完这个BLOG后还有好多DP知识需要知道.....
书回正章。
什么是动态规划呢?
1)动态规划是运筹学中用于求解决策过程中的最优化数学方法。 当然,我们在这里关注的是作为一种算法设计技术,作为一种使用多阶段决策过程最优的通用方法。它是应用数学中用于解决某类最优化问题的重要工具。
2)如果问题是由交叠的子问题所构成,我们就可以用动态规划技术来解决它,一般来说,这样的子问题出现在对给定问题求解的递推关系中,这个递推关系包含了相同问题的更小子问题的解。动态规划法建议,与其对交叠子问题一次又一次的求解,不如把每个较小子问题只求解一次并把结果记录在表中(动态规划也是空间换时间的),这样就可以从表中得到原始问题的解。
哈哈,很专业吧....必须的,这是我从某书抄的.....恩,看不懂吧,我的目的达到了.....
其实,DP用个例子解释起来很简单。
我们来看一个三角.....是三角,没恋.....
如果,我们规定一个游戏规则,从这个三角的上面到下面,每次可以向正下方或者右下方移动,那么求出一个路径让其得到的所有数字和最大,当然了,如果你非得移动出三角,那么那一层你讲获得0.....
有点难懂?我们来举个例子........从开始23开始,假如我们往下移动到右下,那么就获得了55+23,之后继续右下,就是23+55+6,再一次右下,23+55+6+33,这就是一条路径获得的数值。
于是,如何得出一条最大值呢.....从一个点出发,可以得出两个状态,从前面学过的我们可以用搜索.....如果你打算用背包的话.....我不反对.....别说我没阻止你.....
搜索是一个好办法,把所有情况搜索出来,之后挑去最大的就行了,但是假如层数很多怎么办......那样如果用搜索的话.....时间复杂度难以想象.....
我来重新审视这个问题,从最顶端开始,向下有两种选择,正下方,或者右下方.......观察不难发现一个特点,就是第i层的值不受第j层影响(i 在假设一下,如果我们知道第i层的每个方格里的最大值,那么怎么求第i+1层呢?显然,对于i+1的方格值=value[i+1][j] + max(value[i][j], value[i][j+1])......那么,i层最大值和什么有关呢?显然是i-1层,那么i-1层就和i-2层有关.....于是我们推到了第一层,而第一层是固定的,上图就是23,于是我们能反正推回去......我们看一下代码。 于是,我们总结一下什么事DP吧。 首先,DP可以说是搜索的一种特例,它只需要保证每次搜索的结果最优,那么就可以让下一个状态的结果最优,所以,当前状态应该受前面状态制约,而和后面状态无关。 其次,DP都会有一个初始状态是已知的,比如上面第一层,是已知可以直接用的,而且最优解是通过已知展开得到的。 然后,DP都会有一个数组表示一些状态,比如上述的value[i][j]表示的就是走到第i层第j个格子的最大值是多少..... 最后,DP都会有一个叫做动态转移方程的东西......很高端吧......其实就是一个式子,表示当前状态怎么从前面状态得出结果的,比如value[i][j] = map[i][j] + max(value[i - 1][j], value[i - 1][j + 1]);就是一个动态转移方程...... 所以知道上述,DP一般问题就不是问题了...... 来个题试一下:传送门 题目有点晦涩......就是有n个设备,每个设备有流量和价值两个属性,而且每个设备可以由k个厂商生产,于是挑选出来一个方案,让最小流量 / 价值和最大.....是最小流量..... dp[i][j] 表示选到第i件设备,带宽为j 的最小费用。 扯点别的......算法这东西.....以后工作真心没啥用,因为你用的都是成型的东西.....当然你去什么研究室什么的会有用.......不过,作为一个学计算机的,C,C++,Java,PHP什么的语言.....很难么?学一个语言可能需要几个月,但一旦学过一个,学别的就是一个礼拜了......但是算法不是,因为算法说白了就是数学......说白了,你除了会编代码,还要有很好的数学思维.....其实,来吉大的时候,感觉这里的老师还有学生对算法很不重视......真心不知道为什么.......现在从那些准大三里随便抽几个人写单源最短路、最小生成树、网络流什么的,肯定没有能写出来的.........可能是现在中国这种浮躁的学术氛围吧,但是,个人感觉,算法这东西,多学一些特别好...... 还有,关于工作的一点建议,其实,大学本科生来说,不要太好高骛远.....毕竟你只是一个本科,而且不要把吉大想象成什么好大学,你觉得你在吉大不错,其实你出去什么都不是......所以,如果一个职位,工资不太理想,但是很有发展前途,就将就了吧......工资什么的,以后可以张,发展什么的,很难得的......不要因为工资高,而去了一个没有发展的职业.....当然,如果你是女的,我建议你还是嫁的好吧...... so......这是最后一篇写给找工作诸位的BLOG的,祝各位找到好工作吧~~~~value[1][1] = map[1][1];
for (int i = 2; i <= n; ++i)
{
for (int j = 1; j <= i; ++i)
{
value[i][j] = map[i][j] + max(value[i - 1][j], value[i - 1][j + 1]);
}
}
大体就是这样了,可以看出只需要两层循环,复杂度是O(n^2).....显然这比搜索复杂度低很多了。
#include
其实,DP这类题有很多....想练习的可以去POJ搜搜.....