动态规划(一)

1. 分析并掌握“最长公共子序列” 问题的动态规划算法求解方法;

最长公共子序列问题:若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B, C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

 参考程序:

   void LCSLength (char *x ,char *y, int m, int n, int **c, int **b)

{

       int i ,j;

       for (i =1; i <= m; i++) c[i][0] = 0;

       for (i = 1; i <= n; i++) c[0][i] = 0;

       for (i = 1; i <= m; i++)

          for (j = 1; j <= n; j++)

          {

            if (x[i]==y[j])

            {

                 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

            {    c[i][j]=c[i][j-1];

                 b[i][j]=3;

            }

         }

}

void LCS(int i ,int j, char *x ,int **b)

{

      if (i ==0 || j==0) return;

      if (b[i][j]== 1)

      {

           LCS(i-1,j-1,x,b);

           printf("%c",x[i]);

      }

      else if (b[i][j]== 2)

           LCS(i-1,j,x,b);

      else LCS(i,j-1,x,b);

}

 

代码

 

public class ZuiYou {

void LCSLength (char x[] ,char y[], int m, int n, int c[][], int b[][])

{

       int i,j;

       for (i = 0; i <m+1; i++) c[i][0] = 0;

       for (i = 0; i <n+1; i++) c[0][i] = 0;

       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;

        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

        {

        c[i][j]=c[i][j-1];

        b[i][j]=3;

        }

        }

}

void LCS(int i ,int j, char x[] ,int b[][])

{

 if (i ==0 || j==0) return;

 if (b[i][j]== 1)

     {  

 System.out.print(x[i-1]);

  LCS(i-1,j-1,x,b);

       

     }

      else if (b[i][j]== 2)

 LCS(i-1,j,x,b);

else LCS(i,j-1,x,b);

}

public static void main(String[] args) {

ZuiYou zy=new ZuiYou();

char p[]={'A','B','C','B','D'};

char q[]={'B','D','C','A','B'};

int c[][] = new int [p.length+1][q.length+1];

int b[][]=new int[p.length+1][q.length+1];

System.out.print("最长公共子序列为:");

zy.LCSLength(p, q, 5, 5, c, b);

        zy.LCS(5, 5, p, b);

 

}

 

}

截图:

2.最大子段和

给定由n个整数(可能有负整数)组成的序列(a1,a2,…,an),最大子段和问题要求该序列形如的最大值(1<=i<=j<=n),当序列中所有整数均为负整数时,其最大子段和为0。

代码:

import java.util.Scanner;

public class ZiDuanHe {

    int MaxSum(int n,int a[])

    {

     int sum=0,b=0,i=0,besti=0,bestj=0;

     for(int j=0;j<n;j++)

      {

     if(b>0)b+=a[j];

     else{b=a[j];i=j;}

     if(b>sum){sum=b;besti=i;bestj=j;}

     }

     System.out.println(besti);

     System.out.println(bestj);

     System.out.print("最长子段和为:");

     System.out.print(sum);

     return sum;

    }

public static void main(String[] args) {

 

int[] x = new int[6];

Scanner scanner=new Scanner(System.in);

for(int i=0;i<6;i++)

{

x[i]=scanner.nextInt();

}

ZiDuanHe zdh=new ZiDuanHe();

zdh.MaxSum(6, x);

}

}

截图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值