from http://www.cnblogs.com/huenchao/p/5947403.html

1 #include <iostream>
2 using namespace std;
3 #define A_ROWS 3
4 #define A_COLUMNS 2
5 #define B_ROWS 2
6 #define B_COLUMNS 3
7 void matrix_multiply(int A[A_ROWS][A_COLUMNS],int B[B_ROWS][B_COLUMNS],int C[A_ROWS][B_COLUMNS]);
8 int main()
9 {
10 int A[A_ROWS][A_COLUMNS] = {1,0,
11 1,2,
12 1,1};
13 int B[B_ROWS][B_COLUMNS] = {1,1,2,
14 2,1,2};
15 int C[A_ROWS][B_COLUMNS] = {0};
16 matrix_multiply(A,B,C);
17 for(int i=0;i<A_ROWS;i++)
18 {
19 for(int j=0;j<B_COLUMNS;j++)
20 cout<<C[i][j]<<" ";
21 cout<<endl;
22 }
23 return 0;
24 }
25 void matrix_multiply(int A[A_ROWS][A_COLUMNS],int B[B_ROWS][B_COLUMNS],int C[A_ROWS][B_COLUMNS])
26 {
27 if(A_COLUMNS != B_ROWS)
28 cout<<"error: incompatible dimensions."<<endl;
29 else
30 {
31 int i,j,k;
32 for(i=0;i<A_ROWS;i++)
33 for(j=0;j<B_COLUMNS;j++)
34 {
35 C[i][j] = 0;
36 for(k=0;k<A_COLUMNS;k++)
37 C[i][j] += A[i][k] * B[k][j]; //将A的每一行的每一列与B的每一列的每一行的乘积求和
38 }
39 }
40 }
程序测试结果如下所示:

2、矩阵链乘问题描述
给定n个矩阵构成的一个链<A1,A2,A3,.......An>,其中i=1,2,...n,矩阵A的维数为pi-1pi,对乘积 A1A2...An 以一种最小化标量乘法次数的方式进行加全部括号。
注意:在矩阵链乘问题中,实际上并没有把矩阵相乘,目的是确定一个具有最小代价的矩阵相乘顺序。找出这样一个结合顺序使得相乘的代价最低。
3、动态规划分析过程
1)最优加全部括号的结构
动态规划第一步是寻找一个最优的子结构。假设现在要计算AiAi+1....Aj的值,计算Ai...j过程当中肯定会存在某个k值(i<=k<j)将Ai...j分成两部分,使得Ai...j的计算量最小。分成两个子问题Ai...k和Ak+1...j,需要继续递归寻找这两个子问题的最优解。
有分析可以到最优子结构为:假设AiAi+1....Aj的一个最优加全括号把乘积在Ak和Ak+1之间分开,则Ai..k和Ak+1..j也都是最优加全括号的。
2)一个递归解
设m[i,j]为计算机矩阵Ai...j所需的标量乘法运算次数的最小值,对此计算A1..n的最小代价就是m[1,n]。现在需要来递归定义m[i,j],分两种情况进行讨论如下:
当i==j时:m[i,j] = 0,(此时只包含一个矩阵)
当i<j 时:从步骤1中需要寻找一个k(i≤k<j)值,使得m[i,j] =min{m[i,k]+m[k+1,j]+pi-1pkpj} (i≤k<j)。
3)计算最优代价
虽然给出了递归解的过程,但是在实现的时候不采用递归实现,而是借助辅助空间,使用自底向上的表格进行实现。设矩阵Ai的维数为pi-1pi,i=1,2.....n。输入序列为:p=<p0,p1,...pn>,length[p] = n+1。使用m[n][n]保存m[i,j]的代价,s[n][n]保存计算m[i,j]时取得最优代价处k的值,最后可以用s中的记录构造一个最优解。书中给出了计算过程的伪代码,摘录如下:
1 // p是数组,表示维度
2 Matrix_Chain_Order = function (p) {
3
4 var n = p.length - 1; //表示几个矩阵
5 var m = []; //存最大值
6 var s = []; //存路径
7
8
9 //m[0][1] 表示一个矩阵
10 for (var i = 0; i <= n; i++) {
11 m[i] = [];
12 s[i] = [];
13 for (var j = 0; j <= n; j++) {
14
15 m[i][j] = 0;
16 s[i][j] = 0;
17 }
18
19 }
20
21
22 //表示几个矩阵相乘
23 for (var l = 2; l <= n; l++) {
24
25 for (var i = 1; i + l - 1 <= n; i++) {
26
27 var j = i + l - 1;
28
29 m[i][j] = Number.MAX_VALUE;
30
31 for (var k = i; k < j; k++) {
32
33 var temp = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
34
35 if (m[i][j] > temp) {
36
37 m[i][j] = temp;
38 s[i][j] = k;
39 }
40
41 }
42 }
43 }
44
45 return {
46 m: m,
47 s: s
48 };
49 };
50
51
52 var p = [30, 35, 15, 5, 10, 20, 25];
53
54 var str = "";
55
56 //构造最优势解
57 function Print_Optimal_Parens(s, i, j) {
58
59 if (i === j) {
60
61 str += "A" + i;
62
63 } else {
64 str += "(";
65 Print_Optimal_Parens(s, i, s[i][j]);
66 Print_Optimal_Parens(s, s[i][j] + 1, j);
67
68 str += ")";
69
70
71 }
72
73
74 }
75
76
77 var obj = Matrix_Chain_Order(p);
78 var s = obj.s;
79 console.log(obj.m)
80 console.log(obj.s)
81 Print_Optimal_Parens(s, 1, s.length - 1);
82 console.log(str)

1 function LCS(A, B) {
2
3 var m = A.length;
4 var n = B.length;
5 var C = [];
6 var b = [];
7
8 for (var i = 0; i <= m; i++) {
9 C[i] = [];
10 b[i] = [];
11 for (var j = 0; j <= n; j++) {
12
13 C[i][j] = 0;
14 b[i][j] = 0;
15 }
16 }
17
18
19 for (var i = 1; i <= m; i++) {
20 for (var j = 1; j <= n; j++) {
21 if (A[i - 1] == B[j - 1]) {
22 C[i][j] = C[i - 1][j - 1] + 1;
23 b[i][j] = 'left_up';
24 } else {
25 if (C[i - 1][j] >= C[i][j - 1]) {
26 C[i][j] = C[i - 1][j];
27 b[i][j] = 'left';
28 } else {
29 C[i][j] = C[i][j - 1];
30 b[i][j] = 'up';
31 }
32 }
33 }
34 }
35 return {
36 C: C,
37 b: b
38 };
39 }
40
41 function zuiyou(A, b, i, j) {
42 if (i === 0 || j === 0) {
43 return;
44 }
45 if (b[i][j] == 'left_up') {
46 zuiyou(A, b, i - 1, j - 1);
47 console.log(A[i-1]);
48 } else if (b[i][j] == 'left') {
49 zuiyou(A, b, i - 1, j);
50
51 } else {
52 zuiyou(A, b, i, j - 1);
53 }
54 }
55 var A = ['A', 'B', 'C', 'B', 'D', 'A', 'B'];
56 var B = ['B', 'D', 'C', 'A', 'B', 'A'];
57 var len_a = A.length;
58 var len_b = B.length;
59
60
61 var obj = LCS(A, B);
62 console.log(obj.C);
63 console.log(obj.b);
64
65
66 zuiyou(A, obj.b, len_a, len_b);
最长递增子序列:
一, 最长递增子序列问题的描述
设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值。
二, 第一种算法:转化为LCS问题求解
设序列X=<b1,b2,…,bn>是对序列L=<a1,a2,…,an>按递增排好序的序列。那么显然X与L的最长公共子序列即为L的最长递增子序列。这样就把求最长递增子序列的问题转化为求最长公共子序列问题LCS了。
最长公共子序列问题用动态规划的算法可解。设Li=< a1,a2,…,ai>,Xj=< b1,b2,…,bj>,它们分别为L和X的子序列。令C[i,j]为Li与Xj的最长公共子序列的长度。则有递推方程看上面。
这可以用时间复杂度为O(n2)的算法求解,由于这个算法上课时讲过,所以具体代码在此略去。求最长递增子序列的算法时间复杂度由排序所用的O(nlogn)的时间加上求LCS的O(n2)的时间,算法的最坏时间复杂度为O(nlogn)+O(n2)=O(n2)。
三, 第二种算法:动态规划法
设f(i)表示L中以ai为末元素的最长递增子序列的长度。则有如下的递推方程:
f[i] = max(f[j]) + 1
这个递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。
1 var arr = [1, 5, 8, 2, 3, 4];
2
3 function lis(arr) {
4
5 var n = arr.length;
6 var c = [];
7
8 for (var i = 0; i <= n; i++) {
9
10 c[i] = 0;
11
12 }
13
14
15 for (var j = 1; j <= n; j++) {
16
17 c[j] = 1;
18
19 for (var k = 1; k < j; k++) {
20 if (arr[j-1] > arr[k-1] && c[k] >= c[j] - 1) {
21
22 c[j] = c[k] + 1;
23
24 }
25
26 }
27
28 }
29
30 return c;
31 }
32
33 var c =lis(arr);
34 console.log(c);
