https://www.youtube.com/watch?v=_zE5z-KZGRw&list=PLyEvk8ZeQDMVbsg7CEfT0NV3s3GkMx1vN&index=2
把自己觉得有用的东西整理一下.
1.有最优子结构(optimal substructure)时:
第一步,找到最初的状态很关键。
2.没有最优子结构时
①最长路问题
如图,找A到C的最长路,如果有最优子结构,则是从A到D的最长路加D到C的最长路。
但是,A到D的最长路是A>B>C>D;D到C则是D>C,这样就重复了,违反了不能重复走边的原则。
所以这种情况,独立解拼在一起不能构成最优子结构。
②最大团问题:在一个无向图中找出一个点数最多的完全图。不能把团拆开。
3.矩阵乘法
变换到最后4*3的矩阵,总共需要4*6*3 = 72次加法。
如果多个矩阵相乘的话,总的计算次数1700+。如果数字很大,更慢。
所以要给矩阵们括上括号,减少计算次数。
这时就要用动态规划,找出递推方程。
其中的k是指从哪分割。
过程如下:
先把相邻两矩阵之间相乘的状态找出来。
再利用之前算过的,找三个矩阵相乘的:
以此类推,对于每种状态,枚举不同k值下的结果,并找出最小值补充表格。
最后的表格如下:
至于怎么加括号,可以用逆推法。在上述过程中填表的同时,记录下使其值最小的k值。
加括号步骤如下:
找出最优子结构,并根据最优子结构的k值增加括号。
4.Edit distance
字符串相似程度。
问题:如何把一个字符串变为另一个字符串?所花费的最优步骤是什么?
首先,如果要变,需要以下四步:
所以,步骤如下:
one:初始状态是指把0>knitting和kitten>0。存储花费步骤数和操作。
至于为什么是三个方向,把c看做状态,想一想就知道了。
最后回溯。从最后一个格子,根据存储的操作可以找到上一个格子的内容。一直如此就好。
5.最长子序列,最长递增序列。
最长子序列:
行列坐标分别是两个串。*一栏是初始状态,即其中有一个为0时的状态。
通过状态转移方程,如果两个字母一样,就回溯斜方向的状态。如果两个字母不一样,就选取上,左相邻格子里的最大值。
如果要找具体的序列是什么,就回溯。
如图,上方比左方优先,斜方比上方优先,把操作是斜上的格子的字母记下来,走完就好啦!
但是,可以看出里面的最长公共子序列除yxz之外,还有wxy。这个时候,如果回溯,遇到向上箭头且其上,左的值相同,就分两个方向搜。就可以得出其他的LCS。
6.rob cutting
有一个长度为n的杆,已知不同长度的杆价钱不同,问怎样分才能使整根杆的价值最高。
用记忆化的方式dp。
递推方程是怎么得出来的:首先一个整块问题,Cij,取k>=i且<j,此时k是最优分割方案。于是吧问题转换成Cik,Ckj两块,之后以此类推。至于如何确定k的值,根据递推方程,一个个算,找出价值最大时的k值即可。复杂度是o(N^2).
当补充每个状态的最优解时,应存k,以便到最后找到究竟切哪里。
6.0-1 Knapsack Problem
递推方程如下:因为对于一件物品只能选或不选,且物品不能分割。所以当w<M时,直接比较加上或不加的大小就行了。
按方程的步骤走之后,得到表。
如果要打印挑选的物品,应该这样做。
先在最后一个格子,往上搜,如果数字不一样,则是选了最后一个物品,一样则反之,就一直往上搜。
搜到上一格之后,减去上一件物品的重量,然后再往上搜,以此类推。
7.change making
how can a given amount of money be made with the least number of coins of given denominations? It is a knapsack type problem, and has applications wider than just currency.
递推方程如下:
过程如下:
最后回溯,求找了哪几个硬币:
算法复杂度:O(n*k)
8.Maximum Contiguous Subsequence
求出里面和最大的一串子串。
递推方程及步骤如下。
每起始一个子串,标记起始点。
最后找那个最大和子串,从数组里值最大的那个数字开始回溯,直到遇到第一个标记过的起始点。记录路径上经过的点即可。