一、动态规划(dynamic programming)
要点一:动态规划通常用于解决最优化问题。
要点二:最优解和最优解的值是不同的概念,最优解可以有多个,最优解的值只能有一个。
要点三:算法设计包含四个步骤:
(1)描述最优解的结构;
(2)递归定义最优解的值;
(3)按自底向上的方式计算最优解的值;
(4)由计算出的结果构造一个最优解。
要点四:应用动态规划的前提有两个:(1)最优子结构(2)重叠子序列
要点五:《算法导论(第二版)》P192
二、LCS的C++实现
最长公共子序列(Longest-Comment-Subsequence, LCS)
(一)借助数组b来构造最优解的值:
#include <iostream>
#include <stdlib.h>
using namespace std;
//说明:X,Y表示要匹配的两个序列;m,n分别表示X,Y中要进行比较的字符个数。
//由于在序列X,Y和数组c和b中,下标为0的位置都不用,所以:X,Y,c,b可以如下表示:
//X:0,1,...,m; Y:0,1,...,n; c,b:(0,1,...,m )*(0,1,...,n)。即,c和b都是m+1行n+1列
//函数LCS_LENGTH:用于计算LCS的长度(应用数组b做记录)
void LCS_LENGTH(char* X,int m,char* Y,int n,int c[][7],int b[][7])
{
int i,j;
for(i=1;i<=m;i++)
{
c[i][0]=0;
b[i][0]=0;
}
for(j=0;j<=n;j++)
{
c[0][j]=0;
b[0][j]=0;
}
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(*(X+i)==*(Y+j))
{
//c[i,j]=c[i-1,j-1]+1
c[i][j]=c[i-1][j-1]+1;
//↖:1;↑:2;←:3;
//b[i,j]='↖'
b[i][j]=1;
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
//b[i,j]='↑'
b[i][j]=2;
}
else
{
c[i][j]=c[i][j-1];
//b[i,j]='←'
b[i][j]=3;
}
}//for(j...)
}//LCS_LENGTH
//函数PRINT_LCS:用于构造LCS并打印出来(应用数组b)
//n:b数组的列数;i=length(X);j=length(Y)
void PRINT_LCS(int b[][7],int n,char* X,int i,int j)
{
if(i==0||j==0)
return;
if(b[i][j]==1)
{
PRINT_LCS(b,n,X,i-1,j-1);
cout<<*(X+i)<<" ";
}
else if(b[i][j]==2)
PRINT_LCS(b,n,X,i-1,j);
else
PRINT_LCS(b,n,X,i,j-1);
}
//main函数(应用b)
void main()
{
//因为表示序列的字符数组X,Y中的第一位都不用,所以用字符‘0’填充
char X[]="0ABCBDAB";
char Y[]="0BDCABA";
cout<<"LCS-Programming is running!"<<endl;
cout<<"Squence X:A B C B D A B"<<endl;
cout<<"Squence Y:B D C A B A"<<endl;
//设置序列X,Y的长度
int m=7;
int n=6;
int i=m,j=n;
int c[8][7],b[8][7];
cout<<"The LCS length is being computed!"<<endl;
LCS_LENGTH(X,m,Y,n,c,b);
cout<<"The LCS:";
PRINT_LCS(b,n,X,i,j);
system("pause");
}
结果:
二、不借助数组b构造LCS的方法(习题15.4-2):
#include <iostream>
#include <stdlib.h>
using namespace std;
void LCS_LENGTH(char* X,int m,char* Y,int n,int c[][7])
{
int i,j;
for(i=1;i<=m;i++)
c[i][0]=0;
for(j=0;j<=n;j++)
c[0][j]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(*(X+i)==*(Y+j))
c[i][j]=c[i-1][j-1]+1;
else if(c[i-1][j]>=c[i][j-1])
c[i][j]=c[i-1][j];
else
c[i][j]=c[i][j-1];
}//for(j...)
}//LCS-LENGTH
void PRINT_LCS(int c[][7],int n,char* X,int i,int j)
{
if(i==0||j==0)
return;
if(c[i-1][j-1]==c[i][j]-1||c[i-1][j]==c[i][j]-1||c[i][j-1]==c[i][j]-1)
{
PRINT_LCS(c,n,X,i-1,j-1);
cout<<*(X+i)<<" ";
}
else if(c[i][j]==c[i-1][j])
PRINT_LCS(c,n,X,i-1,j);
else
PRINT_LCS(c,n,X,i,j-1);
}
void main()
{
cout<<"LCS-Programming is running!"<<endl;
cout<<"Squence X:A B C B D A B"<<endl;
cout<<"Squence Y:B D C A B A"<<endl;
char X[]="0ABCBDAB";
char Y[]="0BDCABA";
int m=7;
int n=6;
int c[8][7]={0};
int i=m,j=n;
cout<<"The LCS length is being computed!"<<endl;
LCS_LENGTH(X,m,Y,n,c);
cout<<"The LCS:";
PRINT_LCS(c,n,X,i,j);
system("pause");
}
结果: