收藏 分销(赏)

实验02 动态规划算法.doc

上传人:pc****0 文档编号:8313588 上传时间:2025-02-09 格式:DOC 页数:10 大小:94.50KB 下载积分:10 金币
下载 相关 举报
实验02 动态规划算法.doc_第1页
第1页 / 共10页
实验02 动态规划算法.doc_第2页
第2页 / 共10页


点击查看更多>>
资源描述
实验02动态规划算法 [实验目的] 1. 掌握动态规划算法的基本方法 2. 掌握动态规划算法中最优子结构的分析 3. 掌握递归求解最优值的方法 4. 掌握最优解的构造. [预习要求] 1. 认真阅读算法设计教材,了解动态规划原理; 2. 设计用动态规划算法求解矩阵连乘、最长公共子序列以及电路布线的java程序. [实验题] 1. 给定n个矩阵{A1, A2, …,An},其中,Ai与Ai+1是可乘的,计算这n个矩阵的连乘积。从中找出一种乘次数最少的计算次序。 2. 给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。 3. 在一块电路板的上、下2端分别有n个接线柱。根据电路设计,要求用导线(i,π(i))将上端接线柱与下端接线柱相连,确定将哪些连线安排在第一层上,使得该层上有尽可能多的连线。该问题要求确定导线集Nets={(i,π(i)),1≤i≤n}的最大不相交子集。 [实验步骤] 1. 设计并实现算法并准备测试用例,修改并调试程序,直至正确为止; 2. 应用设计的算法和程序求解问题; 3. 将程序整理成功能模块存盘备用. [实验报告要求] 1. 阐述实验目的和实验内容; 2. 阐述求解问题的算法原理; 3. 提交实验程序的功能模块; 4. 记录最终测试数据和测试结果。 [参考] 1.//矩阵连乘类 public class Matrix { private int MN; //表示矩阵链中矩阵的数目 private int[] p; //存放各个矩阵的维数 private int [][][]A; //存放要进行连乘的多个矩阵 private int [][]m; //用来存放Ai到Aj的最少乘次数 private int [][]s; //用来存放Ai到Aj的最后断开位置 // public Matrix() { MN=0; p=new int [MN]; } //构造函数,L为矩阵的数目 public Matrix(int L) { MN=L; p=new int [MN+1]; A=new int [MN][][]; m=new int [MN+1][MN+1]; s=new int [MN+1][MN+1]; //随机生成连乘矩阵的维数[1-11] for(int i=0;i<=MN;i++) { p[i]=(int) Math.round(Math.random()*10)+1; } //随机生成各个矩阵 for(int i=0;i<MN;i++) { A[i]=new int [p[i]][p[i+1]]; CreatMatrix(A[i],p[i],p[i+1]); } } //创建矩阵a,维数为m*n private void CreatMatrix(int [][]a,int m,int n) { for(int i=0;i<m;i++) for(int j=0;j<n;j++) a[i][j]=(int) Math.round(Math.random()*99)-50; } //输出连乘的所有矩阵 private void printAllM() { for (int i=0;i<this.MN;i++) { System.out.println("A"+(i+1)+": "+A[i].length +"*"+A[i][0].length ); printM(A[i]); } } //输出矩阵a的每个元素 private void printM(int [][]a) { for(int i=0;i<a.length ;i++) { System.out.print(" "); for(int j=0;j<a[i].length;j++) System.out.print(String.format("%4d", a[i][j])); System.out.println(); } } public static void main(String [] args) { Matrix M=new Matrix(7); M.printAllM(); M.matrixChain(M.p,M.m,M.s); System.out.print("矩阵链所需的最少乘次数为:"+M.m[1][M.MN]); System.out.println(); String []s=new String[M.MN+1]; for(int i=1;i<=M.MN;i++) { s[i]="A"+i; } M.traceback(M.s, 1, M.MN,s); for(int i=1;i<=M.MN;i++) { System.out.print(s[i]); } } //作用:计算a,b矩阵的乘积,将结果保存在c中, //参数:ra为a的行数,ca为a的列数,rb为b的行数,cb为b的列数 public static void matrixMultiply(int [][]a,int [][]b,int [][]c,int ra,int ca,int rb,int cb) { if(ca!=rb) throw new IllegalArgumentException("矩阵不可乘"); //i为乘积矩阵元素的行下标 for(int i=0;i<ra;i++) //j为乘积矩阵元素的列下标 for (int j=0;j<cb;j++) { //sum初始化为a中i行第一个原素和b中j列第一个元素的乘积 int sum =a[i][0]*b[0][j]; //计算a中第i行和b中第j列对应元素乘积的和 for(int k=1;k<ca;k++) sum+=a[i][k]*b[k][j]; //将乘积的和赋值给乘积矩阵的相应元素 c[i][j]=sum; } } //作用:计算矩阵连乘时,矩阵链的最少乘次数 //参数:p[0:n]表示矩阵A1,A2...An的维数。Ai为p[i-1]*p[i] // m,用来存放矩阵链的最少乘次数,m[i][j]表示A[i,j]最少乘次数 // s,用来存放矩阵链最优次序的断开位置。 public static void matrixChain(int []p, int [][]m, int [][]s) { //n为矩阵个数 int n=p.length-1; //矩阵链长度为1,不需要进行乘运算,即m[i][i]值为0 for (int i=1;i<=n;i++) m[i][i]=0; //计算矩阵链长度大于1的m值 for (int r=2;r<=n;r++) //针对长度为r的各个矩阵链A[i,j]计算最少乘次数m for(int i=1;i<=n-r+1;i++) { int j=i+r-1; //计算初始值m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j] m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j]; //记录对应的断开位置i s[i][j]=i; //断开位置k从i+1到j-1,依次计算m值 for (int k=i+1; k<j; k++) { //计算断开位置为k的乘计算次数,保存到t int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]; //若t比所记录的最少乘计算次数少,则用t替换,并记录新的断开位置 if (t<m[i][j]) { m[i][j]=t; s[i][j]=k; } } } } public static void traceback(int [][]s,int i,int j,String []c) { if(i==j) return; traceback(s,i,s[i][j],c); traceback(s,s[i][j]+1,j,c); c[i]="("+c[i]; c[j]=c[j]+")"; System.out.println("Multiply A"+i+","+s[i][j]+"and A"+(s[i][j]+1)+","+j); } 2.//最长公共子序列类 public class Xl { private char []x; private char []y; private int xl; private int yl; public Xl(int m,int n) { xl=m; yl=n; x=new char [xl]; y=new char [yl]; for(int i=0;i<m;i++) { int t=(int)(Math.random()*8)+65; x[i]=(char) t; } for(int i=0;i<n;i++) { int t=(int)(Math.random()*8)+65; y[i]=(char) t; } } private void print() { for(int i=0;i<this.xl;i++) { System.out.print(String.format("%3s", x[i])); } System.out.println(); for(int i=0;i<this.yl;i++) { System.out.print(String.format("%3s", y[i])); } } public static void main(String []args) { Xl xl1=new Xl(10,12); int [][]b=new int [xl1.xl][xl1.yl]; int lcsl=lcsLength(xl1.x,xl1.y,b); xl1.print(); System.out.println(); System.out.print("最长公共子序列的长度为:"+lcsl); System.out.println(); xl1.lcs(xl1.xl-1,xl1.yl-1,xl1.x, b); } //计算x和y最长公共子序列的长度,b用来记录标记 //最优值存放在c[][]中 public static int lcsLength(char []x,char []y,int [][]b) { int m=x.length-1; int n=y.length-1; int [][]c=new int [m+1][n+1]; //j=0,最长公共子序列为0 for(int i=1;i<= m;i++) c[i][0]=0; //i=0,最长公共子序列为0 for(int i=1;i<= n;i++) c[0][i]=0; //i,j>0时,计算最长公共子序列的长度 for(int i=1;i<= m;i++) for (int j=1;j<=n;j++) { //xi=yj,c[i][j]=c[i-1][j-1]+1 if (x[i]==y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1; } //xi<>yj,c[i][j]=max{c[i][j-1],c[i-1][j] 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; } } return c[m][n]; } //构造最长公共子序列 public 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(String.format("%3s", x[i])); } else if (b[i][j]== 2) lcs(i-1,j,x,b); else lcs(i,j-1,x,b); } } 33333333333333333333333333333333333333333333333333333333333333333.//电路步线 public class WireSet { private int n; //导线的数目 private int m; private int []c; //存放导线 private int [][]size; private int []net; //存放最大公共不相交子集 //构造函数:根据num的值所表示的导线的数目,进行初始化 public WireSet(int num) { n=num; c=new int [n+1]; size=new int [n+1][n+1]; net=new int [n+1]; //对c[]进行赋初值,为1-n的任一个排列 c[1]=(int)(Math.random()*(n)+1); int i=2; while(i<=n) { int f=0; int t=(int)(Math.random()*(n)+1); for(int j=1;j<i;j++) { if (c[j]==t) { f=1; break; } } if (f==0){ c[i]=t; i++; } } } //用来输出相关信息 public void print() { //输出上端线路编号 System.out.print("上端线路编号:"); for(int i=0;i<=n;i++) { System.out.print(String.format("%3d", i)); } System.out.println(); System.out.println(); //输出下端线路编号 System.out.print("下端线路编号:"); for(int i=0;i<=n;i++) { System.out.print(String.format("%3d", c[i])); } System.out.println(); //输出最大不相交子集的个数 System.out.print("最大不相交子集的大小为:"+size[n][n]); System.out.println(); //输出最大不相交子集中的各个导线 System.out.print("上端线路编号:"); for(int i=this.m-1;i>=0;i--) { System.out.print(String.format("%3d", [i])); } System.out.println(); System.out.print("下端线路编号:"); for(int i=this.m-1;i>=0;i--) { System.out.print(String.format("%3d", c[[i]])); } } public static void main(String []args){ WireSet ws= new WireSet(10); //计算最优值 ws.mnset(ws.c, ws.size); //构造最优解 ws.m=ws.traceback(ws.c, ws.size, ); //输出结果 ws.print(); } //[]c:导线上下两端对应的关系:i=c[j],上端i导线对应下端j导线 //size[][]:用来记录最大不相交子集的大小 public static void mnset(int []c,int [][]size) { int n=c.length-1; //j<c[1],i=1,最大不相交子集为空 for(int j=0;j<c[1];j++) size[1][j]=0; //j≥c[1],i=1,最大不相交子集 for(int j=c[1];j<=n;j++) size[1][j]=1; for(int i=2;i<n;i++) { for(int j=0;j<c[i];j++) size[i][j]=size[i-1][j]; for(int j=c[i];j<=n;j++) size[i][j]=Math.max(size[i-1][j],size[i-1][c[i]-1]+1); } size[n][n]=Math.max(size[n-1][n],size[n-1][c[n]-1]+1); } public static int traceback(int []c,int [][]size ,int []net) { int n=c.length-1; int j=n; int m=0; for(int i=n;i>1;i--) if(size[i][j]!=size[i-1][j]) { net[m++]=i; j=c[i]-1; } if(j>=c[1]) net[m++]=1; return m; } }
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 百科休闲 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服