参考文章如下
1. 这个动态规划分析的很详细(转载)
动态规划 基本知识点
**
动态规划
通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。
基本思想
若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
分治与动态规划
共同点:二者都要求原问题具有最优子结构性质,都是将原问题分而治之,分解成若干个规模较小(小到很容易解决的程序)的子问题.然后将子问题的解合并,形成原问题的解.
不同点:分治法将分解后的子问题看成相互独立的,通过用递归来做。
动态规划将分解后的子问题理解为相互间有联系,有重叠部分,需要记忆,通常用迭代来做。
问题特征
最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。
重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。
步骤
描述最优解的结构
递归定义最优解的值
按自底向上的方式计算最优解的值
由计算出的结果构造一个最优解
注意需要需要二维数组用容器,C++动态分配二维数组太坑爹
*****适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)
动态规划例题
1.LCS
寻找最长子序列 ,按照下例,最长为blog 。
cnblogs
belong
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48public class LCS { public static String Lcs_str(String str1 , String str2) { int len1 = str1.length(); int len2 = str2.length(); String str_dp[][] = new String[len1 + 1][len2 + 1]; for(int i = 0 ; i < len1 + 1; i ++ ) { for(int j = 0 ; j < len2 + 1 ; j ++ ) { if( i == 0 || j == 0 ) { str_dp[i][j] = ""; }else if (str1.charAt(i - 1) == str2.charAt(j - 1)) { str_dp[i][j] = str_dp[i-1][j-1] + str1.charAt(i - 1); }else { if(str_dp[i-1][j].length() >= str_dp[i][j-1].length()) { str_dp[i][j] = str_dp[i-1][j]; }else { str_dp[i][j] = str_dp[i][j - 1]; } } } } return str_dp[len1][len2]; } public static int Lcs_int(String str1 , String str2) { int len1 = str1.length(); int len2 = str2.length(); int dp[][] = new int[len1 + 1][len2 + 1]; for(int i = 0 ; i < len1 + 1; i ++ ) { for(int j = 0 ; j < len2 + 1 ; j ++ ) { if( i == 0 || j == 0 ) { dp[i][j] = 0; }else if (str1.charAt(i - 1) == str2.charAt(j - 1)) { dp[i][j] = dp[i-1][j-1] + 1; }else { dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); } } } return dp[len1][len2]; } public static void main(String args[]) { String str1 = "cnblogs"; String str2 = "belong"; System.out.println(Lcs_str(str1, str2)); } }
2. KMP
KMP主要是一个特征向量next存在。 他记载了前缀和后缀的 重复度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54public class KMP { public static int[] getNextArr(String item) { int n = item.length(); int[] next = new int[n+1]; for(int i = 0 ; i < n ; i ++ ) { next[i] = 0; } int i = 0 , j = 1; while( i < n ) { if( j == 0 || item.charAt(i) == item.charAt(j)) { i ++; j ++; next[i] = j; }else { j = next[j]; } } return next; } /* * -2 长度不匹配 * -1 找不到 * 1 - n 匹配成功,str1 出现的第一个位置 * * * 对于str1,str2空 没有考虑 */ public static int kmp(String str1 , String str2) { int[] next = getNextArr(str2); if(str1.length() < str2.length()) { return -2; }else { int pos = 0; pos = next[pos]; for(int i = 0 ; i < str1.length() ; i ++ ) { if(str1.charAt(i) == str2.charAt(pos) && pos == str2.length() - 1) { return (i - str2.length() + 2); }else if( str1.charAt(i) == str2.charAt(pos) ) { pos ++; }else { pos = next[pos]; } } return -1; } } public static void main(String args[]) { System.out.println(kmp("abasdasdabcabasdasdqggd", "abcab")); } }
3 . 最长回文子串
dp[ i ][ j ] == 1 表示 从 i 到 j 的字符串为 回文子串。
第一步 :初步寻找 len = 2 , str[ i ] == str[ i + 1 ] 则得出 dp[ i ][ i + 1 ] = 1; 形成一个 从 i 到 i + 1 的回文子串。
第二步 : 然后判断 dp[i][j] == 1 && str[ i - 1 ] == str[ j + 1] ; 则 len ++ ;
.
.
.
4 .
最后
以上就是朴素龙猫最近收集整理的关于学习笔记 -- 动态规划动态规划 基本知识点动态规划例题的全部内容,更多相关学习笔记内容请搜索靠谱客的其他文章。
发表评论 取消回复