算法设计与分析 实验2

一、 实验目的和要求

 加深对动态规划法的算法原理及实现过程的理解,学习用动态规划法解决实际应用中的最长公共子序列问题和矩阵连乘问题,体会动态规划法和备忘录方法的异同。


二、 实验环境(实验设备)

VisualStudio2017


三、 实验原理及内容

1. 用动态规划法和备忘录方法实现求两序列的最长公共子序列问题。要求掌握动态规划法思想在实际中的应用,分析最长公共子序列的问题特征,选择算法策略并设计具体算法,编程实现两输入序列的比较,并输出它们的最长公共子序列。

2. 用动态规划法和备忘录方法求解矩阵相乘问题,求得最优的计算次序以使得矩阵连乘总的数乘次数最少,并输出加括号的最优乘法算式。


源代码:

#include<iostream> 

#include<string> 

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<iostream>

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 <j;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 <<')';

}




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值