一、 实验目的和要求
加深对动态规划法的算法原理及实现过程的理解,学习用动态规划法解决实际应用中的最长公共子序列问题和矩阵连乘问题,体会动态规划法和备忘录方法的异同。
二、 实验环境(实验设备)
VisualStudio2017
三、 实验原理及内容
1. 用动态规划法和备忘录方法实现求两序列的最长公共子序列问题。要求掌握动态规划法思想在实际中的应用,分析最长公共子序列的问题特征,选择算法策略并设计具体算法,编程实现两输入序列的比较,并输出它们的最长公共子序列。
2. 用动态规划法和备忘录方法求解矩阵相乘问题,求得最优的计算次序以使得矩阵连乘总的数乘次数最少,并输出加括号的最优乘法算式。
源代码:
#include
#include
usingnamespace std;
#defineMaxLength 11
classLCS
{
public:
LCS(intnx, intny, char *x, char *y) //对数据成员m、n、a、b、c、s初始化
{
m= nx; n = ny; //对m和n赋值
a= newchar[m + 2]; //考虑下标为0的元素和字符串结束标记
b= newchar[n + 2];
memset(a,0, m + 2);
memset(b,0, n + 2);
for (int i = 0; i < nx + 2; i++)
a[i+ 1] = x[i];
for (int i = 0; i < ny + 2; i++)
b[i+ 1] = y[i];
c= newint[MaxLength][MaxLength]; //maxlength为某个常量值
s= newint[MaxLength][MaxLength];
memset(c,0, sizeof(c));
memset(s,0, sizeof(s));
}
int LCSLength();
void CLCS()
{
CLCS(m, n);
}
private:
void CLCS(inti, intj) const;
int(*c)[MaxLength], (*s)[MaxLength];
int m, n;
char *a, *b;
};
intLCS::LCSLength()
{
for (int i = 1; i <= m;i++) //初始化行标或列标为0的元素
c[i][0]= 0;
for (int j = 1; j <= n;j++)
c[0][j]= 0;
for (int i = 1; i <= m;i++)
{
for (int j = 1; j <= n;j++)
{
if (a[i] == b[j]) //由c[i-1][j-1]得到c[i][j]
{
c[i][j]= c[i - 1][j - 1] + 1;
s[i][j]= 1;
}
elseif (c[i - 1][j] >=c[i][j - 1]) //由c[i-1][j]得到c[i][j]
{
c[i][j]= c[i - 1][j];
s[i][j]= 2;
}
else//由c[i][j-1]得到c[i][j]
{
c[i][j]= c[i][j - 1];
s[i][j]= 3;
}
}
}
return c[m][n]; //返回最优解值
}
voidLCS::CLCS(inti, intj) const
{
if (i == 0 || j == 0 || s[i][j] == 0)
return; //终止条件
if (s[i][j]==1) {
CLCS(i-1,j-1);
cout<<a[i]; //输出最优解的当前分量
}
else
if (s[i][j] == 2)
CLCS(i - 1, j);
else
CLCS(i, j - 1);
}
int main()
{
int nx, ny;
char *x = newchar[MaxLength], *y = newchar[MaxLength];
cout <<"请仅输入字母 !"<< endl;
cout<<"请输入X :"<< endl;
cin >> x;
nx =strlen(x);
cout<<"请输入Y :"<< endl;
cin >> y;
ny =strlen(y);
LCS lcs(nx, ny, x, y);
cout<<"X和Y最长公共子序列的长度为:"<< lcs.LCSLength() << endl;
cout<<"该序列为"<< endl;
lcs.CLCS();
cout<< endl;
delete[]x;
delete[]y;
return 0;
}
四、 矩阵连乘问题源代码
#include
usingnamespace std;
void MatrixChain(intn, int *p, int **m, int **s);
void Traceback(inti, intj, int **s);
int main()
{
int p[4] = {50,10,40,30 };
int q[6] = {30,35,15,5,10,20 };
int **m = newint*[100];
for (int i = 0; i <= 100;++i)
{
m[i]= newint[100];
}
int **s = newint*[100];
for (int i = 0; i <= 100;++i)
{
s[i]= newint[100];
}
MatrixChain(4,p, m, s);
Traceback(1,4, s);
system("pause");
return 0;
}
void MatrixChain(intn, int *p, int **m, int **s)
{
for (int i = 1; i <= n; i++)
m[i][i] = 0;
for (int r = 2; r <= n; r++) {
for (int i = 1; i <= n - r + 1; i++) {
int j = i + r - 1;
m[i][j] = m[i + 1][j] + p[i] * p[i + 1] * p[j + 1];//省略m[i][i]=0;
s[i][j] = i;
for (int k = i + 1; k
{
double t = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1];
if (t < m[i][j]) {
m[i][j] = t;
cout<<"更新m["<< i <<"]["<< j <<"]的值为:"<< t << endl;
s[i][j] = k;
cout<<"更新m["<< i <<"]["<< j <<"]的值为:"<< k << endl;
}
}
cout<<"最终求出:m["<< i <<"]["<< j <<"]的值为 :"<<m[i][j] << endl;
}
}
}
void Traceback(inti, intj, int **s)
{
if (i == j) { cout <<'A'<<i<<' '; return; }
if (i<s[i][j]) cout <<'(';
Traceback(i, s[i][j], s);
if (i<s[i][j]) cout <<')';
if (s[i][j] + 1<j) cout <<'(';
Traceback(s[i][j] + 1, j, s);
if (s[i][j] + 1<j) cout <<')';
}