實驗5 動態規劃實驗一

OJ練習
1. Multiplication Puzzle:http://poj.org/problem?id=1651
2. 【該題可以轉化爲矩陣連乘問題】
3. Common Subsequence:http://poj.org/problem?id=1458
4. 【該題只需要輸出最長公共子序列的長度】
3*. Human Gene Functions:Human Gene Functions:http://poj.org/problem?id=1080【LCS變形】
4*. Compromise:http://poj.org/problem?id=2250【LCS問題】
5*. AGTC:http://poj.org/problem?id=3356【LCS問題】
6*.完美序列:http://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1539

實驗內容
1. 最長公共子序列問題(LCS)。在使用動態規劃算法來求解最長公共子序列時,二維數組c[i][j]用於記錄序列Xi和Yj的最長公共子序列的長度,對於序列X = {A, C, B, C, D, A, B, D}和Y = {A, B, D, C, A, B, A},繪製對應的c[i][j]。
所繪製的c[i][j]數組:


        A   C   B   C   D   A   B   D
    0   0   0   0   0   0   0   0   0
A   0   1   1   1   1   1   1   1   1
B   0   1   1   2   2   2   2   2   2
D   0   1   1   2   2   3   3   3   3
C   0   1   2   3   3   3   3   3   3
A   0   1   2   2   3   3   4   4   4
B   0   1   2   3   3   3   4   5   5
A   0   1   2   3   3   3   4   5   5
  1. 最長公共子序列問題(LCS)。分別使用備忘錄法和動態規劃算法求解最長公共子序列的長度。【輸入:兩個字符序列;輸出:兩個字符序列的最長公共子序列的長度。例如:輸入序列A = “ABCBDAB”,序列B = “BDCABA”;輸出4】
    備忘錄法源代碼:
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#define maxn 105
#define maxm 10005
#define INF 0x3f3f3f3f
using namespace std;

char a[maxn],b[maxn];
int dp[maxn][maxn],c[maxn][maxn];
int n,m;

int lcs1(int i, int j)
{
    if(dp[i][j]) return dp[i][j];
    if(!i || !j) return 0;
    else if(a[i-1] == b[j-1])
        dp[i][j] = lcs1(i-1,j-1)+1;
    else
        dp[i][j] = max(lcs1(i-1,j), lcs1(i,j-1));

    return dp[i][j];
}


int main()
{
    while(cin >> a >> b){
        memset(dp,0,sizeof(dp));
        n = strlen(a);
        m = strlen(b);
        lcs1(n,m);
        cout << dp[n][m] << endl;
    }
}
/*
ABCBDAB
BDCABA
*/

動態規劃算法源代碼:

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#define maxn 105
#define maxm 10005
#define INF 0x3f3f3f3f
using namespace std;

char a[maxn],b[maxn];
int dp[maxn][maxn],c[maxn][maxn];
int n,m;
void lcs1(int n, int m)
{
    for(int i=1; i<=n; i++){
        for(int j=1;j<=m; j++){
            if(a[i-1]==b[j-1]){
                dp[i][j] = dp[i-1][j-1] + 1;
                c[i][j] = 1;
            }
            else if(dp[i-1][j] >= dp[i][j-1]){
                dp[i][j] = dp[i-1][j];
                c[i][j] = 2;
            }
            else{
                dp[i][j] = dp[i][j-1];
                c[i][j] = 3;
            }
        }
    }
}

void lcs2(int i, int j)
{
    if(!i || !j) return ;
        if(c[i][j] == 1){
            lcs2(i-1,j-1);
              printf("%c",a[i-1]);
        }
        else if(c[i][j]==2){
            lcs2(i-1,j);
        }
        else{
            lcs2(i,j-1);
        }
}

int main()
{
    while(cin >> a >> b){
        memset(dp,0,sizeof(dp));
        memset(c,0,sizeof(c));
        n = strlen(a);
        m = strlen(b);
         lcs1(n,m);
         cout << endl;
         cout << dp[n][m] << endl;
    }
}
/*
ABCBDAB
BDCABA
*/


  1. 最長公共子序列問題(LCS)。在練習2代碼的基礎上,使用動態規劃算法構造一條最長公共子序列。【輸入:兩個字符序列;輸出:兩個字符序列的一條最長公共子序列。例如:輸入序列A = “ABCBDAB”,序列B = “BDCABA”;輸出”BCAB”(或其他任意一條長度爲4的公共子序列)】
    源代碼:
#include<queue>
#include<iostream>
#define maxn 105
#define maxm 10005
#define INF 0x3f3f3f3f
using namespace std;

char a[maxn],b[maxn];
int dp[maxn][maxn],c[maxn][maxn];
int n,m;
void lcs1(int n, int m)
{
    for(int i=1; i<=n; i++){
        for(int j=1;j<=m; j++){
            if(a[i-1]==b[j-1]){
                dp[i][j] = dp[i-1][j-1] + 1;
                c[i][j] = 1;
            }
            else if(dp[i-1][j] >= dp[i][j-1]){
                dp[i][j] = dp[i-1][j];
                c[i][j] = 2;
            }
            else{
                dp[i][j] = dp[i][j-1];
                c[i][j] = 3;
            }
        }
    }
}

void lcs2(int i, int j)
{
    if(!i || !j) return ;
        if(c[i][j] == 1){
            lcs2(i-1,j-1);
              printf("%c",a[i-1]);
        }
        else if(c[i][j]==2){
            lcs2(i-1,j);
        }
        else{
            lcs2(i,j-1);
        }
}

int main()
{
    while(cin >> a >> b){
        memset(dp,0,sizeof(dp));
        memset(c,0,sizeof(c));
        n = strlen(a);
        m = strlen(b);
         lcs1(n,m);
         lcs2(n,m);
         cout << endl;
         cout << dp[n][m] << endl;
    }
}
/*
ABCBDAB
BDCABA
*/
  1. 求如圖所示一個上三角矩陣中每一條斜線中的最大元素(L)和最小元素(S)。
    輸入:
    1 3 5 7 11 20
    6 8 2 3 13
    7 4 8 9
    18 3 10
    12 6
    15
    輸出:
    L1 = 18, S1 = 1
    L2 = 8, S2 = 3
    L3 = 10, S3 = 2
    L4 = 9, S4 = 3
    L5 = 13, S5 = 11
    L6 = 20, S6 = 20
    源代碼:
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<bits/stdc++.h>
#define maxn 105
#define maxm 10005
#define INF 0x3f3f3f3f
using namespace std;

int a[maxn][maxn];
int n,m;
int Max = -INF, Min = INF;
int main()
{
    n = 6;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            cin >> a[i][j];
        }
    }
    for(int r=1; r<=n; r++){
        int Max = -INF, Min = INF;
        for(int i=1; i<=n-r+1; i++){
            int j = i + r - 1;
            Max = max(Max,a[i][j]);
            Min = min(Min,a[i][j]);
        }
        cout << "L1 = " << Max << ", " << "S1 = " << Min << endl;
    }
    return 0;
}
/*
1 3 5 7 11 20
0 6 8 2 3 13
0 0 7 4 8 9
0 0 0 18 3 10
0 0 0 0 12 6
0 0 0 0 0 15
*/
5. 矩陣連乘問題。使用動態規劃算法求解矩陣連乘問題。【輸入:一個存儲矩陣維數的一維數組;輸出:矩陣連乘最優計算次序。】

例如:
輸入:
一維數組{30, 35, 15, 5, 10, 20, 25}
輸出:
A[2:2] * A[3:3]
A[1:1] * A[2:3]
A[4:4] * A[5:5]
A[4:5] * A[6:6]
A[1:3] * A[4:6]
源代碼:

/*
#include<iostream>
using namespace std;
#define N 7

void MatrixChainOrder(int *p,int (*m)[N],int (*s)[N],int length)
{
    int n=length-1;
    int l,i,j,k,q=0;
    for(i=1;i<length;i++)
    {
        m[i][i]=0;
    }
    for(l=2;l<=n;l++)
    {
        for(i=1;i<=n-l+1;i++)
        {
            j=i+l-1;
            m[i][j]=0x7fffffff;
            for(k=i;k<=j-1;k++)
            {
                q=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
                if(q<m[i][j])
                {
                    m[i][j]=q;
                    s[i][j]=k;
                }
            }
        }
    }
    cout << m[1][N-1] << endl;
}
void Print(int(*s)[N],int i,int j)
{
    if(i==j)
    {
        cout<<"A"<<i;
    }
    else
    {
        cout<<"(";
        Print(s,i,s[i][j]);
        Print(s,s[i][j]+1,j);
        cout<<")";
    }
}
int main()
{
    int p[N]={20,35,15,5,10,20,25};
    int m[N][N],s[N][N];
    MatrixChainOrder(p,m,s,N);
    Print(s,1,N-1);
    return 0;
}

*/
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<bits/stdc++.h>
#define maxn 105
#define maxm 10005
#define INF 0x3f3f3f3f
using namespace std;

int a[maxn][maxn];
int n,m;
int Max = -INF, Min = INF;

void matrixChain(int *p, int **dp, int **s,int n)
{
    for(int i=1; i<=n; i++) dp[i][i] = 0;
    for(int r=2; r<=n; r++){
        for(int i=1; i<=n-r+1; i++){
            int j = i + r - 1;
            dp[i][j] = dp[i+1][j] + p[i-1]*p[i]*p[j];
            s[i][j] = i;
        for(int k=i+1; k<j; k++){
            int t = dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j];
            if(t < dp[i][j]){
                dp[i][j] = t;
                s[i][j] = k;
              }
          }
      }

    }
    cout << dp[1][n-1] << endl;
}

void dfs(int **s, int i, int j)
{
    if(i==j) return ;
    dfs(s,i,s[i][j]);
    dfs(s,s[i][j]+1,j);
    cout<<"A["<<i<<":"<<s[i][j]<<"]";
    cout<<" * A"<<"["<<(s[i][j]+1)<<":"<<j<<"]"<<endl;
}
int main()
{
    int p[7]={30,35,15,5,10,20,25};
    int **s = new int *[7];
    int **dp = new int *[7];
    for (int i=0 ; i<7 ; ++i)
    {
        s[i]= new int[7];
        dp[i] = new int[7];
    }
    matrixChain(p,dp,s,6);
    cout<<endl;
    dfs(s,1,6);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章