一、实验目的
理解并实践动态规划算法。
二、 实验要求
完成教材第3章10个应用范例中的至少4个(任选4个实现即可)。
三、实验步骤与内容
(1)矩阵连乘问题:
#include<iostream>
#include<iomanip>
#include<string.h>
using namespace std;
const int sz= 20;
void MatrixChain(int *p, int m[sz][sz], int s[sz][sz], int length) {
for (int i = 1;i<= length; i++) {
m[i][i] = 0;
}
for (int r = 2; r <= length; r++) {
for (int i = 1; i <= length;i++) {
int j = i + r - 1;
m[i][j] = m[i + 1][j]+ p[i - 1] * p[i] * p[j];
s[i][j] = i;
for (int k = i + 1; k < j; k++) {
int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (t < m[i][j]) {
m[i][j] = t;
s[i][j] = k;
}
}
}
}
}
void printMatrix(int m[sz][sz] ,int length) {
for (int i = 1; i <= length; i++) {
for (int j = 1; j <= length; j++) {
cout << setw(6) << setfill(' ') << m[i][j] << " ";
}
cout << endl;
}
}
void printresult(int s[sz][sz], int i, int j) {
if (i == j)
{
cout << "A" << i;
}
else
{
cout << "(";
printresult(s, i, s[i][j]);
printresult(s, s[i][j] + 1, j);
cout << ")";
}
}
int main() {
int n;
int p[sz], m[sz][sz], s[sz][sz];
memset(p, 0, sizeof(p));
memset(m, 0, sizeof(m));
memset(s, 0, sizeof(s));
cout << "请输入矩阵的个数:" ;
cin >> n;
for (int i = 0; i <= n; i++) {
cout << "请输入"<<(i+1)<<"的下标:";
cin >> p[i];
}
cout << "你输入的矩阵为:" << endl;
for (int i = 0; i <n; i++) {
cout << "A" << (i + 1) << "[" << p[i] << "]"
<< "[" << p[i + 1] << "] ";
}
cout << endl;
cout << "m矩阵为:" << endl;
MatrixChain(p, m, s, n);
printMatrix(m, n);
cout << "s矩阵为:" << endl;
printMatrix(s, n);
printresult(s, 1, n);
cout << endl;
system("pause");
return 0;
}
结果:
(2)最长公共子序列:
#include <iostream>
using namespace std;
const int X = 100, Y = 100;
char result[X+1];
int count=0;
int Lcs_Length(string x, string y, int b[][Y+1],int xlen,int ylen)
{
int i = 0;
int j = 0;
int c[X+1][Y+1];
for (i = 0; i<=xlen; i++)
{
c[i][0]=0;
}
for (i = 0; i <= ylen; i++ )
{
c[0][i]=0;
}
for (i = 1; i <= xlen; i++)
{
for (j = 1; j <= ylen; j++)
{
if (x[i - 1] == y[j - 1])
{
c[i][j] = c[i-1][j-1]+1;
b[i][j] = 1;
}
else
{
if ( c[i-1][j] > c[i][j-1] )
{
c[i][j] = c[i-1][j];
b[i][j] = 2;
}
else
{
if( c[i-1][j] < c[i][j-1] )
{
c[i][j] = c[i][j-1];
b[i][j] = 3;
}
else
{
c[i][j] = c[i][j-1];
b[i][j] = 4;
}
}
}
}
}
cout << "推导过程:" << endl;
for(i = 1; i <= xlen; i++)
{
for(j = 1; j < ylen; j++)
{
cout << c[i][j] << " ";
}
cout << endl;
}
return c[xlen][ylen];
}
void Display_Lcs(int i, int j, string x, int b[][Y+1],int current_len,int lcs_max_len)
{
if (i ==0 || j==0)
{
cout << "最长公共子序列:" ;
for(int s=0; s < lcs_max_len; s++)
{
cout << result[s];
}
cout<<endl;
count++;
return;
}
if(b[i][j]== 1)
{
current_len--;
result[current_len]=x[i- 1];
Display_Lcs(i-1, j-1, x, b,current_len,lcs_max_len);
}
else
{
if(b[i][j] == 2)
{
Display_Lcs(i-1, j, x, b,current_len,lcs_max_len);
}
else
{
if(b[i][j]==3)
{
Display_Lcs(i, j-1, x, b,current_len,lcs_max_len);
}
else
{
Display_Lcs(i,j-1,x,b,current_len,lcs_max_len);
Display_Lcs(i-1,j,x,b,current_len,lcs_max_len);
}
}
}
}
int main(int argc, char* argv[])
{
string x = "ABCBEDABC";
string y = "BDCEABAC";
cout<< "序列A:" << x <<endl;
cout<< "序列B:" << y <<endl;
int xlen = x.length();
int ylen = y.length();
int b[X + 1][Y + 1];
int lcs_max_len = Lcs_Length( x, y, b, xlen,ylen );
cout << "最长子序列长度:" << lcs_max_len << endl;
Display_Lcs( xlen, ylen, x, b, lcs_max_len, lcs_max_len );
cout << "共有:" << count << "个" <<endl;
return 0;
}
结果:
(3)最大子段和
#include <iostream>
using namespace std;
int MaxSum(int n,int *a);
int main()
{
int a[] = {-20,11,-4,13,-5,-2};
cout<<"序列为:";
for(int i=0; i<6; i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
cout<<"最大连续子段和为:"<<MaxSum(5,a)<<endl;
return 0;
}
int MaxSum(int n,int *a)
{
int sum=0,b=0;
for(int i=1; i<=n; i++)
{
if(b>0)
{
b+=a[i];
}
else
{
b=a[i];
}
if(b>sum)
{
sum = b;
}
}
return sum;
}
结果:
(4)凸多边形最优三角剖分
#include <iostream>
using namespace std;
const int N = 7;
const int M = 7;
int weight[M][N] =
{
{0,2,2,3,1,4},
{2,0,1,5,2,3},
{2,1,0,2,1,4},
{3,5,2,0,6,2},
{1,2,1,6,0,1},
{4,3,4,2,1,0}
};
int MinWeightTriangulation(int n,int **t,int **s);
void Traceback(int i,int j,int **s);
int Weight(int a,int b,int c);
int main()
{
cout<<"凸多边形的弦集合如下:"<<endl;
for(int i=0;i<6;i++)
{
for(int j=0;j<6;j++)
{
cout<<weight[i][j]<<" ";
}
cout<<endl;
}
int **s = new int *[N];
int **t = new int *[N];
for(int i=0;i<N;i++)
{
s[i] = new int[N];
t[i] = new int[N];
}
cout<<endl;
cout<<"此多边形的最优三角剖分值为:"<<MinWeightTriangulation(N-1,t,s)<<endl;
cout<<"最优三角剖分结构为:"<<endl;
Traceback(1,5,s);
return 0;
}
int MinWeightTriangulation(int n,int **t,int **s)
{
for(int i=1; i<=n; i++)
{
t[i][i] = 0;
}
for(int r=2; r<=n; r++)
{
for(int i=1; i<=n-r+1; i++)
{
int j = i+r-1;
t[i][j] = t[i+1][j] + Weight(i-1,i,j);
s[i][j] = i;
for(int k=i+1; k<j; k++)
{
int u = t[i][k] + t[k+1][j] + Weight(i-1,k,j);
if(u<t[i][j])
{
t[i][j] = u;
s[i][j] = k;
}
}
}
}
return t[1][N-2];
}
void Traceback(int i,int j,int **s)
{
if(i==j) return;
Traceback(i,s[i][j],s);
Traceback(s[i][j]+1,j,s);
cout<<"三角剖分顶点:V"<<i-1<<",V"<<j<<",V"<<s[i][j]<<endl;
}
int Weight(int a,int b,int c)
{
return weight[a][b] + weight[b][c] + weight[a][c];
}
结果: