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);
}
}
截图: