算法分析与设计实验二(关于动态规划问题)

第一个实验是求矩阵连乘问题

这个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

 

    原文作者:动态规划
    原文地址: https://blog.csdn.net/sinat_26598193/article/details/68491230
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞