• 第15章DP(转)


    15.1-1 由公式(15.3)和初始条件T(0) = 1,证明公式(15.4)成立。

    ANSWER:

     15.1-2 举反例证明下面的“贪心”策略不能保证总是得到最优切割方案。定义长度为i的钢条的密度为Pi / i,即每英寸的价值。贪心策略将长度为n的钢条切割下长度为i (1 ≤ i ≤ n)的一段,其密度最高。接下来继续使用相同的策略切割长度为n-i的剩余部分。

    ANSWER:当长度n = 4时,按照“贪心”策略则切割成长度为1和3的钢条(p = 1 + 8 = 9);而最优解为切割成2条长度为2的钢条(p = 5 + 5 = 10 > 9)。

     15.1-3 我们对钢条切割问题进行一点修改,除了切割下的钢条段具有不同价值Pi外,每次切割还要付出固定的成本c。这样,切割方案的收益就等于钢条段的价格之和减去切割成本。设计一个动态规划算法解决修改后的钢条切割问题。

    ANSWER:多新建一个数组m[0...n]记录每个长度的钢条最优解的切割段数,当完成长度为i的钢条最优解时,更新长度为i+1时使m[i+1] = m[j] + 1,其中长度为i+1的钢条切割成长度为(i+1-j)和j的两大段,长度为j的钢条继续切割。

                   BOTTOM_UP_CUT_ROD_COST(p, n, c):  
    1.     let r[0...n] and m[0...n] be new arrays  
    2.     r[0] = 0, m[0] = 0  
    3.     for i = 1 to n  
    4.         q = -∞  
    5.         for j = 1 to i  
    6.             if q < p[j] + r[i-j] - m[i-j]*c  
    7.                 q = p[j] + r[i-j] - m[i-j]*c  
    8.                 m[i] = m[i-j] + 1  
    9.         r[i] = q  
    10.     return r[n]
     
    //15.1-3带有固定切割成本的钢条切割方案
    #if 0
    #include <iostream>
    using namespace std;
    int Max(int a,int b)
    {
        return a>b?a:b;
    }
    struct array
    {
        int r;//代表最大收益
        int s;//代表切割方案
    };
    struct array *EXTENDED_BOTTOM_UP_CUT_ROD(int p[],int n)
    {
        struct array *rs=new struct array[n];
        rs[0].r=0;
        int q;
        for (int j=0;j<n;j++)
        {
            int flag=1;//哨兵为1代表无切割。
            q=p[j];
            for (int i=0;i<j;i++)
            {
                //q=Max(q,p[i]+rs[j-i].r-1);
                if(q<=p[i]+rs[j-i].r-1)//切割固定成本c=1
                {
                    q=p[i]+rs[j-i].r-1;
                    rs[j+1].s=i+1;
                    flag=0;//哨兵为0代表有切割。
                }
            }
            if (j==i)//i=j代表无切割
            {
                if (q<=p[i]+rs[j-i].r&&flag)
                {//无切割时注意切割方案就等于钢条长度。
                    rs[j+1].s=i+1;
                }
            }
            rs[j+1].r=q;
        }
        return rs+n;
    }
    void PRINT_CUT_ROD_SOLUTION(int p[],int n)
    {
        struct array *rs=EXTENDED_BOTTOM_UP_CUT_ROD(p,n);
        while (n>0)
        {
            cout<<(*rs).s<<" ";
            n=n-(*rs).s;
            rs=rs-(*rs).s;
        }
    }
    void main()
    {
        const int n=10;
        int p[10]={1,5,8,9,10,17,17,20,24,30};
        cout<<(*EXTENDED_BOTTOM_UP_CUT_ROD(p,10)).r<<endl;
        PRINT_CUT_ROD_SOLUTION(p,10);
    }
    View Code

    15.1-4 修改MEMOIZED-CUT-ROD,使之不进返回最优收一只,还返回切割方案。

    ANSWER:利用数组s的结果可以得到切割方案,新建存储长度为n的钢条切割方案数组t[0...n]

             CUT_WAY(s, n):  

    1.     i = 0  
    2.     while n > 0  
    3.         t[i] = s[n]  
    4.         n = n - s[n]  
    5.         i = i + 1  
    6.     return t[0...i-1]
     1 //15.1-4动态规划法递归求解最优钢条切割问题。不仅返回收益还返回切割方案。
     2 #include <iostream>
     3 using namespace std;
     4 struct array
     5 {
     6     int r;//代表最大收益
     7     int s;//代表切割方案
     8 };
     9 int Max(int a,int b)
    10 {
    11     return a>b?a:b;
    12 }
    13 struct array *MEMOIZED_CUT_ROD_AUX(int p[],int n,struct array rs[])
    14 {
    15     static int q;
    16     if (rs[n].r>=0)
    17     {
    18         return rs+n;
    19     }
    20     if (n==0)
    21     {
    22         q=0;
    23     } 
    24     else
    25     {
    26         q=-0x7fffffff;
    27         for (int i=0;i<n;i++)
    28         {
    29             int t=p[i]+MEMOIZED_CUT_ROD_AUX(p,n-i-1,rs)->r;
    30             if (q<t)
    31             {
    32                 q=t;
    33                 rs[n].s=i+1;//n相当于上面迭代里的j+1,i+1和上面迭代一样。
    34             }
    35         }
    36     }
    37     rs[n].r=q;
    38     return rs+n;
    39 }
    40 struct array *MEMOIZED_CUT_ROD(int p[],int n)
    41 {
    42     struct array *rs=new struct array [n];
    43     for (int i=0;i<=n;i++)
    44     {
    45         rs[i].r=-0x7fffffff;
    46     }
    47     return MEMOIZED_CUT_ROD_AUX(p,n,rs);
    48 }
    49 void PRINT_CUT_ROD_SOLUTION(int p[],int n)
    50 {
    51     struct array *rs=MEMOIZED_CUT_ROD(p,n);
    52     cout<<"最大收益:"<<rs->r<<endl;
    53     cout<<"切割方案:";
    54     while (n>0)
    55     {
    56         cout<<(*rs).s<<" ";
    57         n=n-(*rs).s;
    58         rs=rs-(*rs).s;
    59     }
    60 }
    61 void main()
    62 {
    63     const int n=10;
    64     int p[10]={1,5,8,9,10,17,17,20,24,30};
    65     PRINT_CUT_ROD_SOLUTION(p,10);
    66     cout<<endl;
    67 }
    View Code

    15.1-5 斐波那契数列可以用递归式(3.22)定义。设计一个O(n)时间的动态规划算法计算第n个斐波那契数。画出字问题图。图中有多少顶点和边?

    ANSWER:O(n)时间,O(1)空间

    1. On_for_Fibonacci_sequence(n):  
    2.     if n <= 2  
    3.         return 1  
    4.     x = 1, y = 1  
    5.     for i = 3 to n  
    6.         res = x + y  
    7.         x = y  
    8.         y = res  
    9.     return res

    子问题图:

    图中有n个顶点,(2n-3)条边。

    15.2-1 对矩阵规模序列{5,10,3,12,5,50,6},求矩阵链最优括号化方案。

    利用上面代码:得到下图所示结果:

    15.2-2设计递归算法MATRIX-CHAIN-MULTIPLY(A,s,i,j),实现矩阵链最优代价乘法计算的真正计算过程,其输入参数为矩阵序列{A1,A2,...,An},MATRIX-CHAIN-ORDER得到的表s,以及下标i和j.(初始调用应为MATRIX-CHAIN-MULTIPLY(A,s,1,n)).

      1 #include <iostream>
      2 using namespace std;
      3 #define n 5//可以更改矩阵的数量
      4 struct Matrix
      5 {
      6     int rows;//表示行数。
      7     int columns;//表示列数。
      8     int **M;
      9     Matrix(int i=0,int j=0)
     10     {
     11       rows=i;
     12       columns=j;
     13       M=new int *[rows];
     14       for (int k=0;k<rows;k++)
     15       {
     16            M[k]=new int [columns];
     17       }
     18     };
     19 };
     20 struct Matrix_CHAIN//矩阵链
     21 {
     22      int **m;//运算次数
     23      int **s;//划分方式    
     24      Matrix_CHAIN()
     25      {
     26          m=new int *[n-1];
     27          for (int k=0;k<n-1;k++)
     28          {
     29              m[k]=new int [n-1];
     30          }
     31          s=new int *[n-2];
     32          for (int t=0;t<n-1;t++)
     33          {
     34              s[t]=new int [n-1];
     35          }
     36      }
     37 };
     38 struct Matrix init(struct Matrix A)
     39 {
     40     for (int i=0;i<A.rows;i++)
     41     {
     42         for (int j=0;j<A.columns;j++)
     43         {
     44             A.M[i][j]=rand()%10;
     45         }
     46     }
     47     return A;
     48 }
     49 struct Matrix Matrix_MULTIPLY(struct Matrix A,struct Matrix B)
     50 {
     51    if (A.columns!=B.rows)
     52    {
     53        struct Matrix D(1,1);
     54        D.M[0][0]=0;
     55        cerr<<"incompatible dimensions"<<endl;
     56        return D;
     57    } 
     58    else
     59    {
     60        struct Matrix C(A.rows,B.columns);
     61          for (int i=0;i<A.rows;i++)
     62          {
     63              for (int j=0;j<B.columns;j++)
     64              {
     65                  C.M[i][j]=0;
     66                  for (int k=0;k<A.columns;k++)
     67                  {
     68                      C.M[i][j]=C.M[i][j]+A.M[i][k]*B.M[k][j];
     69                  }
     70              }
     71          }
     72          return C;
     73    }
     74 }
     75 struct Matrix_CHAIN MATRIX_CHAIN_ORDER(int p[])
     76 {
     77     int N=n-1;
     78     Matrix_CHAIN T;
     79     for (int i=0;i<N;i++)
     80     {
     81         T.m[i][i]=0;
     82     }
     83     for (int l=2;l<=N;l++)
     84     {
     85         for (int i=1;i<=N-l+1;i++)
     86         {
     87             int j=i+l-1;
     88             T.m[i-1][j-1]=0x7fffffff;
     89             for (int k=i;k<=j-1;k++)
     90             {
     91                 int q=T.m[i-1][k-1]+T.m[k][j-1]+p[i-1]*p[k]*p[j];
     92                 if (q<T.m[i-1][j-1])
     93                 {
     94                     T.m[i-1][j-1]=q;
     95                     T.s[i-1][j-1]=k-1;
     96                 }
     97             }
     98         }
     99     }
    100     return T;
    101 }
    102 //15.2-2矩阵链总乘法
    103 struct Matrix MATRIX_CHAIN_MULTIPLY(Matrix A[],Matrix_CHAIN T,int i,int j)
    104 {
    105     if (j==i)
    106     {
    107         return A[i];
    108     }
    109     if (j==i+1)
    110     {
    111         return Matrix_MULTIPLY(A[i],A[j]);
    112     }
    113     Matrix t1=MATRIX_CHAIN_MULTIPLY(A,T,i,T.s[i][j]);
    114     Matrix t2=MATRIX_CHAIN_MULTIPLY(A,T,T.s[i][j]+1,j); 
    115     return Matrix_MULTIPLY(t1,t2);
    116 }
    117 void PRINT_OPTIMAL_PARENS(Matrix_CHAIN T,int i,int j)
    118 {
    119    if (i==j)
    120    {
    121        cout<<"A"<<i;
    122    } 
    123    else
    124    {
    125        cout<<"(";
    126        PRINT_OPTIMAL_PARENS(T,i,T.s[i][j]);
    127        PRINT_OPTIMAL_PARENS(T,T.s[i][j]+1,j);
    128        cout<<")";
    129    }
    130 }
    131 void Print(struct Matrix A)
    132 {
    133     for (int i=0;i<A.rows;i++)
    134     {
    135         for (int j=0;j<A.columns;j++)
    136         {
    137             cout<<A.M[i][j]<<" ";
    138         }
    139         cout<<endl;
    140     }
    141 }
    142 void main()
    143 {
    144     //int p[n]={5,10,3,12,5,50,6};
    145     //int p[n]={30,35,15,5,10,20,25};
    146     int p[n]={2,3,4,5,6};
    147     struct Matrix_CHAIN T=MATRIX_CHAIN_ORDER(p);
    148     for (int i=0;i<n-1;i++)
    149     {
    150         for (int j=0;j<n-1;j++)
    151         {
    152             if (T.m[i][j]<0)
    153             {
    154                 cout<<"-1"<<"	";
    155             }
    156             else cout<<T.m[i][j]<<"	";
    157         }
    158         cout<<endl;
    159     }
    160     PRINT_OPTIMAL_PARENS(T,0,n-2);
    161     struct Matrix A[n]={0};
    162     for (int j=1;j<n;j++)
    163     {
    164         struct Matrix t(p[j-1],p[j]);
    165         A[j-1]=t;
    166         init(A[j-1]);
    167         cout<<endl;
    168         Print(A[j-1]);
    169         cout<<endl;
    170     }
    171     struct Matrix C=MATRIX_CHAIN_MULTIPLY(A,T,0,n-2);
    172     Print(C);
    173 }
    View Code

    由于数组下标是从0开始的,所以 这里调用应为MATRIX-CHAIN-MULTIPLY(A,s,0,n-2)).n为矩阵链元素个数,上面代码中的n为矩阵链长度,实际矩阵个数N=n-1个。

    15.2-3 用代入法证明递归公式(15.6)的结果为Ω(2^n).

    P(n-1)=P(1)P(n-2)+P(2)P(n-3)+....+P(n-2)P(1)    P(n)=P(1)P(n-1)+P(2)P(n-2)+....+P(n-1)P(1)   因为P(1)<P(2)<...P(n-1) 所以P(n)>P(1)P(n-1)+P(n-1)   因为P(1)=1 P(n)>2P(n-1)

    猜想P(n)>c2^n,则P(n-1)>c2^(n-1) 所以P(n)>2c2^(n-1)=c2^n 得证!

    15.2-4 对输入链长度为n的矩阵连乘法问题,描述其子问题图:它包含多少个顶点?包含多少条边?这些分别连接哪些顶点?

    包含n²个顶点,n³条边连接着n²个顶点。

    15.2-5 令R(i,j)表示在一次调用MATRIX-CHAIN-ORDER过程中,计算其他表项时访问表项m[i,j]的次数。证明:(提示:证明中可用到公式A.3)

    15.2-6 证明:对n个元素的表达式进行完全括号化,恰好需要n-1对括号。

         利用归纳法即可证明。当n≤2时 恰好有1对括号。假设当n=k(2<k<n)时,有k-1对括号。则n=k+1时,现在我们把这k+1个矩阵分成k个矩阵+1个矩阵,前k个矩阵在前面假设中已知只要加k-1对括号就可以使最终结果是最优的,那么保持前k个矩阵的括号划分,并且得到最优结果矩阵后,再与第k+1个矩阵相乘,这时问题又转化为2个矩阵相乘的简单问题了,由前面已知需要1对括号,那么总的括号就是k-1+1=k对括号,在n=k+1时,也成立。所以利用归纳法得证!

    15.3动态规划原理

    15.3-1对于矩阵链乘法问题,下面两种确定最优代价的方法哪种更高效?第一种方法是穷举所有可能的括号化方案,对每种方案计算乘法运算次数,第二种方法是运行RECURSIVE-MATRIX-CHAIN。证明你的结论。

    书中对枚举法已经给出其运行时间,就是类似卡塔兰数的序列,运算次数为Ω(4^n/n^(3/2))。而用朴素递归方式求全部解的运算次数为O(n3^n).显然用递归方式求解更高效。

    15.3-2 对一个16个元素的数组,画出2,.3-1节中MERGE-SORT过程运行的递归调用树。解释备忘技术为什么对MERGE-SORT这种分治算法无效。

    参考书中图2-4,这里只是把原书8个元素扩展到16个元素,两者类似。由2-4图可以看出,每个子问题都是全新的,不存在重叠子问题,所以图中问题适合分治而不适合动态规划。

    15.3-3 考虑矩阵链乘法问题的一个变形,目标改为最大化矩阵序列括号花方案的变量乘法运算次数,而非最小化。此问题具有最优子结构性质吗?

    由于矩阵链中的子问题链为AiAi+1...Ak和Ak+1Ak+2....Aj的乘法问题,子链是互不相交的,因此任何矩阵都不会同时包含在两个子链中。这样我们说矩阵链子问题是无关的。于是我们可以用“剪切-黏贴”技术来加以证明这个事具有最优子结构的。

    15.3-3思路供参考:确定一个问题是否具有最优子结构要考虑两个方面的问题:1、子问题是否是独立。2、子问题是否是重叠
    先分析第一个问题:最大矩阵链乘法子问题是将矩阵链分为两部分,求前一部和后一部分最大值,然后合并,而这两个子问题的 最大值是在两个矩阵链中分别求解,所以这两个子问题没有重复(在这里最鲜明的对照就是无权图中最长简单路径问题,该问题如果分为两个子问题,前一部分的最长路径可能包含后一部分的最长路径,两个子问题合并之后的路径就不是简单路径了)。再看子问题是否重叠,如果子问题中的子问题是一个跟子问题不一样的问题则为不重叠,如果将子问题的矩阵链分解为两个孙矩阵链,同样是求两个孙矩阵链各自的最大值然后合并,该孙子问题与子问题相同,即为重叠,所以最大矩阵链乘法具有最优子结构。

    代码如下:

    #include<iostream>
    using namespace std;
    //p为矩阵链,p[0],p[1]代表第一个矩阵,p[1],p[2]代表第二个矩阵,length为p的长度
    //所以如果有六个矩阵,length=7,m为存储最优结果的二维矩阵,t为存储选择最优结果路线的
    //二维矩阵
    void MatrixChainOrder(int *p,int (*m)[10],int (*t)[10],int length)
    {
        int n=length-1;
        int i,j,k,q,num=0;
        //A[i][i]只有一个矩阵,所以相乘次数为0,即m[i][i]=0;
        for(i=1;i<length;i++)
        {
            m[i][i]=0;
        }
        //i代表矩阵链的长度,i=2表示有两个矩阵相乘时如何划分
        for(i=2;i<=n;i++)
        {
            //j表示从第j个矩阵开始的i个矩阵如何划分是最优
            for(j=1;j<=n-i+1;j++)
            {
                //k为从第j个数i个矩阵就是k,从j到k表示他们之间的i个矩阵如何划分
                k=j+i-1;
                //m[j][k]存储了从j到k使用最佳划分所得到的最优结果
                m[j][k]=0;
                //q为介于j到k-1之间的数,目的是利用q对j到k之间的矩阵进行试探性的划分,
                //从而找到最优划分,这是一种遍历性的试探。
                for(q=j;q<=k-1;q++)
                {
                    num=m[j][q]+m[q+1][k]+p[j-1]*p[q]*p[k];
                    if(num>m[j][k])
                    {
                        m[j][k]=num;
                        t[j][k]=q;
                    }
                }
            }
        }
    }
    void PrintAnswer(int(*t)[10],int i,int j)
    {
        if(i==j)
        {
            cout<<"A"<<i;
        }
        else
        {
            cout<<"(";
            PrintAnswer(t,i,t[i][j]);
            PrintAnswer(t,t[i][j]+1,j);
            cout<<")";
        }
    }
    int main()
    {
        int p[7]={30,35,15,5,10,20,25};
        int m[10][10],t[10][10];
        MatrixChainOrder(p,m,t,7);
    //    MemorizedMatrixChain(p,m,t,7);
        PrintAnswer(t,1,6);
        cout<<endl;
        cout<<m[1][6]<<endl;
        return 0;
    }
    View Code

     15.3-4 <1,1,2,3> 

    贪心:[1,3]=[1,1]+[2,3]+1*1*3=1*2*3+3=9
    正确结果:[1,3]=[1,2]+[3,3]+1*2*3=1*1*2+6=8

    15.3-5 对15.1节的钢条切割问题加入限制条件:假定对于每种钢条长度i(i=1,2,...n-1),最多允许切割出li段长度为i的钢条。证明:15.1节所描述的最优子结构性质不再成立。

    从图中看出如果切割1个长度为4的钢条,最佳切割方式是切成4条长度为1的钢条可以获得60最大收益,但是我们给每种长度对应的条数做了限制,比如长度为1的钢条最多只能切割2段,那么4>2超出预期。所以我们在不违反切割限制前提下只能选择切成长度分别为1,1和2的钢条作为最佳切割方式,收益为50。由于加了切割限制,所以最优子结构性质不再成立。

    最优子结构:问题的最优解由相关子问题的最优解组合而成,而这些子问题可以独立求解。
    因为此时每种长度的切割数被限制,也就是说此时使用长度i时,会影响子问题的li 大小,是相关的(可以把每种长度的限制加入状态中,来消除相关性。但维数太多无法实现)。即建立[rn ,L],L为li 集合,但是子问题的状态数很大,几乎等于穷举了

    15.3-6

    Dm =max{(Di -ci )ri,j }=max{Diri,j -ci *ri,j },两个子问题相关,具有同样变量ri,j

    15.4.1

    15.4-2

    //LCS
    #include<iostream>
    #include<string>
    using namespace std;
    
    //改进的LCS算法,不使用数组b便可打印出结果
    void LCS_LengthC(string x,string y,int (*c)[100])
    {
        int m,n;
        m=x.length();
        n=x.length();
        int i,j;
        //如果i或j等于0则c[i][j]=0;
        for(i=1;i<=m;i++)
        {
            c[i][0]=0;
        }
        for(i=1;i<=n;i++)
        {
            c[0][i]=0;
        }
        //遍历两个字符串,依次标记c[i][j],c[i][j]标记了从x的开始到第i个元素与从
        //y开始到第j个元素中LCS的长度
        //数组b用来标记最长公共子串所要走的路线,该路线为两个字符串组成的矩阵中的对应的字母
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(x[i-1]==y[j-1])
                {
                    c[i][j]=c[i-1][j-1]+1;
                }
                else
                {
                    if(c[i][j-1]>c[i-1][j])
                    {
                        c[i][j]=c[i][j-1];
                    }
                    else
                    {
                        c[i][j]=c[i-1][j];
                    }
                }
            }
        }
    }
    void PrintAnswerC(string x,string y,int(*c)[100],int i,int j)
    {
        if(i==0||j==0)
        {
            return ;
        }
        else
        {
            if(x[i-1]==y[j-1])
            {
                PrintAnswerC(x,y,c,i-1,j-1);
                cout<<x[i-1]<<" ";
            }
            else if(c[i-1][j]>=c[i][j-1])
            {
                PrintAnswerC(x,y,c,i-1,j);
            }
            else
            {
                PrintAnswerC(x,y,c,i,j-1);
            }
        }
    }
    int main()
    {
        string x="abcbda";
        string y="bdcaba";
        int c[100][100]={0};
        int b[100][100]={0};
        LCS_LengthC(x,y,c);
        cout<<"the LCS is: "<<c[x.length()][y.length()]<<endl;
        PrintAnswerC(x,y,c,x.length(),y.length());
        return 0;
    
    }
    View Code

    15.4-3

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int lcsLength(int **c,char *x,char *y,int i,int j)
    {
        if(i<0 || j<0)
            return -1;
        if(c[i][j] != -1)
            return c[i][j];
        if(x[i-1]==y[j-1])
        {
            int a=lcsLength(c,x,y,i-1,j-1);
            c[i][j]=a+1;        
        }
        else
        {
            int up=lcsLength(c,x,y,i-1,j);
            int left=lcsLength(c,x,y,i,j-1);
            if(up>=left)
                c[i][j]=up;    
            else
                c[i][j]=left;
        }
        return c[i][j];
    }
    
    int** initC(char *x,char *y)
    {
        int xlen=strlen(x);
        int ylen=strlen(y);
        int **c=(int**)malloc((xlen+1)*sizeof(int*));
        for(int i=0;i<xlen+1;i++)
        {
            c[i]=(int*)malloc((ylen+1)*sizeof(int));
        }
        for(int i=0;i<xlen+1;i++)
            for(int j=0;j<ylen+1;j++)
                c[i][j]=-1;
        for(int i=0;i<xlen+1;i++)
            c[i][0]=0;
        for(int j=0;j<ylen+1;j++)
            c[0][j]=0;
        return c;
    }
    
    void printLCS(int **c,char *x,char *y)  
    {  
        int xlen=strlen(x);  
        int ylen=strlen(y);  
        int i=xlen,j=ylen;  
        char *s=(char*)malloc((xlen)*sizeof(char));  
        while(i>=1 && j>=1)  
        {  
            if(x[i-1]==y[j-1])  
            {  
                s[i-1]=x[i-1];  
                i--;  
                j--;  
            }  
            else if(c[i][j]==c[i-1][j])  
            {  
                s[i-1]='*';  
                i--;              
            }  
            else  
                j--;  
        }  
        for(;i<xlen;i++)  
        {  
            if(s[i]!='*')  
                printf("%c ",s[i]);  
        }  
        printf("
    ");
    } 
    
    void printC(int **c,int xlen,int ylen)
    {
        for(int i=1;i<xlen+1;i++)
        {
            for(int j=1;j<ylen+1;j++)
            {
                if(c[i][j]==-1)
                    printf("%d ",c[i][j]);
                else
                    printf("%d  ",c[i][j]);
            }
            printf("
    ");
        }
    }
    
    void main()
    {
        char *x="ABCBDAB";
        char *y="BDCABA";
        int **c=initC(x,y);
        lcsLength(c,x,y,strlen(x),strlen(y));
        printLCS(c,x,y);
        //printC(c,strlen(x),strlen(y));
        getchar();
    }
    View Code
  • 相关阅读:
    hdu3486 Interviewe (二分+线段树求区间最值)
    hdu2473 JunkMail Filter(并查集)
    hdu3290 The magic apple tree (dfs)
    hdu2610 Sequence one (dfs) &&hdu2611 Sequence two
    hdu1598 find the most comfortable road (枚举+并查集)
    hdu3635 Dragon Balls
    hdu2821 Pusher
    hdu1558 Segment set
    hdu 2514 Another Eight Puzzle
    url传递中文的解决方案
  • 原文地址:https://www.cnblogs.com/mhpp/p/7692532.html
Copyright © 2020-2023  润新知