第一个实验是求矩阵连乘问题
这个m和s是用6*6二维数组
package test1;
import java.util.Scanner;
import java.util.*;
public class test1 {
voidMatrixChain(int p[],int n,int m[][],int s[][])//m[6][6] s[6][6] p[7] n=5
{
for(inti=0;i<n;i++)m[i][i]=0;
for(intr=1;r<n;r++){
for(inti=0;i<n-r;i++){
intj=i+r;
m[i][j]=m[i+1][j]+p[i]*p[i+1]*p[j+1];
s[i][j]=i+1;
for(intk=i;k<j;k++){
intt=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];
if(t<m[i][j]){
m[i][j]=t;
s[i][j]=k+1;
}
}
}
}
}
voidTraceback(int i,int j,int s[][]){
if(i==j)return;
Traceback(i,s[i-1][j-1],s);
Traceback(s[i-1][j-1]+1,j,s);
System.out.printf("MultiplyA(%d,%d) and A(%d,%d)", i,s[i-1][j-1],s[i-1][j-1]+1,j);
}
publicstatic void main(String[] argn){
intp[]={30,35,15,5,10,20,25};
intn=6;
intm[][]=new int[n][n];
ints[][]=new int[n][n];
test1a=new test1();
a.MatrixChain(p,n, m, s);
for(inti=0;i<n;i++){
for(intj=0;j<n;j++)
{
System.out.printf("%6d",m[i][j]);
}
System.out.println();
}
System.out.println("----------------------------------");
for(inti=0;i<n;i++){
for(intj=0;j<n;j++)
{
System.out.printf("%6d",s[i][j]);
}
System.out.println();
}
a.Traceback(1,6,s);
}
}
—
(改)n*n变成n+1*n+1二维数组即此题7*7且if(i==0|| j==0) a[i][j]=0;
package test1;
import java.util.Scanner;
import java.util.*;
public class test1 {
voidMatrixChain(int p[],int n,int m[][],int s[][])//m[6][6] s[6][6] p[7] n=5
{
for(inti=1;i<=n;i++)m[i][i]=0;
for(intr=2;r<=n;r++){
for(inti=1;i<=n-r+1;i++){
intj=i+r-1;
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(intk=i+1;k<j;k++){
intt=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(t<m[i][j]){
m[i][j]=t;
s[i][j]=k;
}
}
}
}
}
voidTraceback(int i,int j,int s[][]){
if(i==j)return;
Traceback(i,s[i][j],s);
Traceback(s[i][j]+1,j,s);
System.out.printf("MultiplyA%d,%d and A%d,%d", i,s[i][j],s[i][j]+1,j);
}
publicstatic void main(String[] argn){
intp[]={30,35,15,5,10,20,25};
intn=6;
int m[][]=new int[n+1][n+1];
int s[][]=new int[n+1][n+1];
test1a=new test1();
a.MatrixChain(p,n, m, s);
for(inti=1;i<=n;i++){
for(intj=1;j<=n;j++)
{
System.out.printf("%6d",m[i][j]);
}
System.out.println();
}
System.out.println("----------------------------------");
for(inti=1;i<=n;i++){
for(intj=1;j<=n;j++)
{
System.out.printf("%6d",s[i][j]);
}
System.out.println();
}
a.Traceback(1,6,s);
}
}
c语言版(同学需要,在java的基础上改成c= =)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void MatrixChain(int p[],int n,int **m,int **s)//m[6][6] s[6][6] p[7] n=5
{
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-1]*p[i]*p[j];
s[i][j]=i;
for(int k=i+1;k<j;k++){
int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(t<m[i][j]){
m[i][j]=t;
s[i][j]=k;
}
}
}
}
}
void Traceback(int i,int j,int **s){
if(i==j)return;
Traceback(i,s[i][j],s);
Traceback(s[i][j]+1,j,s);
printf("Multiply A%d,%d and A%d,%d\n", i,s[i][j],s[i][j]+1,j);
}
int main(){
int p[]={30,35,15,5,10,20,25};
int n=6;
// int m[][]=new int[n+1][n+1];
// int s[][]=new int[n+1][n+1];
int **m;
int **s;
m=(int **)malloc((n+1)*sizeof(int *));
s=(int **)malloc((n+1)*sizeof(int *));
for(int i=0;i<n+1;i++)
{ m[i]=(int *)malloc((n+1)*sizeof(int ));
s[i]=(int *)malloc((n+1)*sizeof(int ));}
for(int i=0;i<n+1;i++)
for(int j=0;j<n+1;j++){
s[i][j]=0;
m[i][j]=0;
}
MatrixChain(p, n, m, s);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
{
printf("%6d",m[i][j]);
}
printf("\n");
}
printf("----------------------------------\n");
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
{
printf("%6d",s[i][j]);
}
printf("\n");
}
Traceback(1,6,s);
return 0;
}
矩阵连乘问题实际是从底向上进行计算。r的作用是让ij呈↘方向进行。r是由2到6(5次循环),此时的i是1到n-r+1即1-5,1-4,1-3,1-2,1-1;j是i+r-1,即2-6,3-6,4-6,5-6,6-6即第一个循环r=2实际是有m[1][2],m[2][3],m[3][4],m[4][5],m[5][6]。
r=3时是有m[1][3],m[2][4],m[3][5],m[4][6];
r=4时是有m[1][4],m[2][5],m[3][6];
r=5时是有m[1][5],m[2][6];
r=6时是有m[1][6];
然后
m[i][j] { ①0 ,i=j
②min{m[i][k]+m[k+1][j]+p[i-1]p[k]p[j]}(i<=k<j) , i<j
可以通过代码中定义的自变量为K的循环在i->j中实现比较取最小。
此题还可以通过备忘录的方法进行解答,算法大概思路是,先把m[i][j]循环遍历赋值0
然后写一个方法参数是i,j,比如方法叫做LookupChain(int i,int j)
把上面的m[x]][y]换成LookupChain(x,y);即可。
LookupChain(int i,int j){
if(m[i][j]>0) return m[i][j];
if(i==j)return 0;
int u=LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
…类似
}
实验2:最长公共子序列
package test1;
import java.util.Scanner;
import java.util.*;
public class test1 {
/* c[i][j]{ 0 i=j=0;
* c[i-1][j-1]+1 i,j>0;xi=yi;
* max{c[i][j-1],c[i-1][j]} i,j>0;xi!=yi;
* */
static void LCSLength(int m,int n,char x[],char y[],int c[][],int b[][]){//c b [m][n]
int i,j;
for(i=0;i<=m;i++)c[i][0]=0;
for(i=0;i<=n;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][j-1]<=c[i-1][j]){
c[i][j]=c[i-1][j];
b[i][j]=2;
}
else{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
}
static 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);
System.out.print(x[i-1]);
}
else if(b[i][j]==2)LCS(i-1,j,x,b);
else if(b[i][j]==3)LCS(i,j-1,x,b);
}
public static void main(String[] argn){
char x[]={'A','B','C','B','D','A','B'};
char y[]={'B','D','C','A','B','A'};
int c[][]=new int[x.length+1][y.length+1];
int d[][]=new int[x.length+1][y.length+1];
LCSLength(x.length,y.length,x,y,c,d);
System.out.print(" ");
for(int j=0;j<y.length;j++)
System.out.print(y[j]+" ");
System.out.println();
for(int i=0;i<=x.length;i++){
if(i!=0)
System.out.print(x[i-1]);
else
System.out.print(" ");
for(int j=0;j<=y.length;j++)
{
System.out.printf("%3d",c[i][j]);
}
System.out.println();
}
System.out.println("----------------------------------");
System.out.print(" ");
for(int j=0;j<y.length;j++)
System.out.print(y[j]+" ");
System.out.println();
for(int i=0;i<=x.length;i++){
if(i!=0)
System.out.print(x[i-1]);
else
System.out.print(" ");
for(int j=0;j<=y.length;j++)
{
System.out.printf("%3d",d[i][j]);
}
System.out.println();
}
LCS(x.length,y.length,x,d);
}
}
实际上c[i][o] =0 c[0][j]=0;
然后i,j均到m,n遍历,m是X的长度,n是Y的长度。然后内部通过这种比较方式.
c[i][j]={① 0,i=0,j=0
②c[i-1][j-1]+1,i>0,j>0,x[i]=y[j]
③max{c[i][j-1],c[i-1][j] }i,j>0,x[i]!=y[j]
以书上的数据x={A,B,C,B,D,A,B};Y={B,D,C,A,B,A}为例得出最长公共子序列为BCBA