实验三动态规划.docx
《实验三动态规划.docx》由会员分享,可在线阅读,更多相关《实验三动态规划.docx(17页珍藏版)》请在冰豆网上搜索。
实验三动态规划
算法分析与设计实验报告
学号
姓名
班级
上课地点
教师
上课时间
1.实验目的
1.1理解动态规划算法的主要设计思想和基本步骤;
1.2掌握用动态规划策略解决实际问题。
2.实验环境
2.1Eclipse
2.2WindowXP
3.实验内容
3.1矩阵连乘问题
3.2最长公共子序列问题
3.30-1背包问题
4.教师批改意见
签字:
日期:
成绩
实验报告细表
1.矩阵连乘问题
1.1算法设计思想
(1)分析最优解:
计算A[i:
j]的最优次序所包含的计算矩阵子链A[i:
k]和A[k+1:
j]的次序也是最优的
(2)建立递归关系:
设计算A[i:
j],1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]
当i=j时,A[i:
j]=Ai,因此,m[i,i]=0,i=1,2,…,n
当i可以递归地定义m[i,j]为:k的位置有j-i种可能(3)计算最优值:用动态规划算法解此问题,可依据其递归式以自底向上的方式进行计算。在计算过程中,保存已解决的子问题答案。每个子问题只计算一次,而在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法publicstaticvoidMatrixChain(int[]p,int[][]m,int[][]s){intn=p.length-1;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][i][j];s[i][j]=i;for(intk=i+1;k{intt=m[i][k]+m[k+1][j]+p[i-1][k][j];if(tm[i][j]=t;s[i][j]=k;}}}}(4)构造最优解:算法matrixChain记录了构造最优解所需的全部信息。s[i][j]=k表明计算矩阵链A[i:j]的最佳方式在矩阵Ak和Ak+1之间断开,即最优的加括号方式为(A[i:k])(A[k+1:j])。因此,从s[1][n]记录的信息可知计算A[1:n]的最优加括号方式为(A[1:s[1][n]])(A[s[1][n]+1:n])。而A[1:s[1][n]]的最优加括号方式为(A[1:s[1][s[1][n]]])(A[s[1][s[1][n]]+1:s[1][s[1][n]]])。同理可以确定A[s[1][n]+1:n]的最优加括号方式在s[s[1][n]+1][n]处断开。照此递推下去,最终可以得到A[1:n]的最优完全加括号方式,即构造出问题的一个最优解。publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}1.2程序源码矩阵连乘代码:/***下面是矩阵连乘问题的动态规划算法*假设有6个矩阵:*A1A2A3A4A5A6*30*3535*1515*55*1010*2020*25则matrixChain为*{30,35,15,5,10,20,25}结果为*((A1*(A2*A3))*((A4*A5)*A6))*@authorzhanlingxia*/packagejuzhenliancheng;publicclassjuzhenliancheng{publicstaticvoidmain(String[]args){int[]p={30,35,15,5,10,20,25};//矩阵的维数存放于数组p中matrixMultiply(p);}//矩阵连乘publicstaticvoidmatrixMultiply(int[]p){intdimen=p.length;int[][]m=newint[dimen][dimen];//定义了存放最优值数组mint[][]s=newint[dimen][dimen];//定义了记录断开位置的数组sMatrixChain(p,m,s);System.out.println("最优乘法次数:"+m[1][dimen-1]);System.out.println("划分规则为:");traceback(s,1,dimen-1);}/*1:首先计算出m[i][i]2:然后根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。。。3:计算m[i][j]时,只要用到m[i][k]和m[k+1][j]*/publicstaticvoidMatrixChain(int[]p,int[][]m,int[][]s){intn=p.length-1;for(inti=1;i<=n;i++)m[i][i]=0;//计算单一矩阵//根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。。。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{intt=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];//更新m[i][j],s[i][j]的值if(t{m[i][j]=t;s[i][j]=k;}}}}//按算法MatrixChain计算出断点矩阵s指示的加括号方式publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}}1.3实验结论1.4心得体会算法设计真的需要逻辑思维,能得到结果挺开心的。2:最长公共子序列2.1算法设计思想(1)设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk},则若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列。若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列(2)建立递归关系:由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。用c[i][j]记录序列和的最长公共子序列的长度。其中,Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。其他情况下,由最优子结构性质可建立递归关系如下:(3)计算最优值:算法lcsLength以序列X={x1,x2…xm}和Y={y1,y2…ym}作为输入。输出两个数组c和b。其中,c[i][j]存储Xi和Yj的最长公共子序列的长度,b[i][j]记录c[i][j]的值是由哪一个子问题的解得到的,问题的最优值存放于c[m][n]中publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}elseif(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;}}returnc[m][n];}(4)构造最优解:publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}2.2程序源码最长公共子序列代码:/***下面是最长公共子序列问题的动态规划算法*char[]x={'A','B','C','D','A','B'};*char[]y={'B','D','C','A','B','A'};*打印结果为CAB*@authorzhanlingxia*/packagezuichanggonggongzixulie;publicclasszuichanggonggongzixulie{/*计算最优值c[i][j]存储Xi和Yi的最长公共子序列的长度b[i][j]记录c[i][j]的值是由最长公共子序列*/publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];//空序列最长公共子序列for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;//对角线+1for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}//和上面一样elseif(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;}}returnc[m][n];}//打印最长公共子序列publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}publicstaticvoidmain(Stringargs[]){char[]x={'A','B','C','D','A','B'};char[]y={'B','D','C','A','B','A'};int[][]b=newint[x.length+1][y.length+1];System.out.println("最长公共子序列:");intn=lcsLength(x,y,b);System.out.println();System.out.println("其长度为:"+n);System.out.println("最长公共子序列为:");lcs(x.length-1,y.length-1,x,b);}}2.3实验结论2.4心得体会:最长公共子序列比较好理解哦。做起来也相较简单多了30-1背包问题3.1算法设计思想(1)分析最优解:设(y1,y2,…,yn)是所给0-1背包问题的一个最优解,则(y2,…,yn)是下面相应子问题的一个最优解。(2)建立递归关系:设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。(3)计算最优值:publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}(4)构造最优解:publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}3.2程序源码0-1背包问题代码:/***下面是0-1的动态规划算法*v[]w[]c分别是价值、重量、和背包容量数组*m[i][j]表示有i~n个物品,背包容量为j的最大价值。*@authorzhanlingxia*/publicclassbeibao{publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}publicstaticvoidmain(String[]args){//测试int[]w={2,2,6,5,4};int[]v={6,3,5,4,6};int[][]m=newint[11][11];System.out.println("0-1背包问题最优值:");knapsack(v,w,10,m);System.out.println("0-1背包问题最优解:");int[]x=newint[w.length];traceback(m,w,10,x);for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
可以递归地定义m[i,j]为:
k的位置有j-i种可能
(3)计算最优值:
用动态规划算法解此问题,可依据其递归式以自底向上的方式进行计算。
在计算过程中,保存已解决的子问题答案。
每个子问题只计算一次,而在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法
publicstaticvoidMatrixChain(int[]p,int[][]m,int[][]s)
{
intn=p.length-1;
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][i][j];
s[i][j]=i;
for(intk=i+1;k{intt=m[i][k]+m[k+1][j]+p[i-1][k][j];if(tm[i][j]=t;s[i][j]=k;}}}}(4)构造最优解:算法matrixChain记录了构造最优解所需的全部信息。s[i][j]=k表明计算矩阵链A[i:j]的最佳方式在矩阵Ak和Ak+1之间断开,即最优的加括号方式为(A[i:k])(A[k+1:j])。因此,从s[1][n]记录的信息可知计算A[1:n]的最优加括号方式为(A[1:s[1][n]])(A[s[1][n]+1:n])。而A[1:s[1][n]]的最优加括号方式为(A[1:s[1][s[1][n]]])(A[s[1][s[1][n]]+1:s[1][s[1][n]]])。同理可以确定A[s[1][n]+1:n]的最优加括号方式在s[s[1][n]+1][n]处断开。照此递推下去,最终可以得到A[1:n]的最优完全加括号方式,即构造出问题的一个最优解。publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}1.2程序源码矩阵连乘代码:/***下面是矩阵连乘问题的动态规划算法*假设有6个矩阵:*A1A2A3A4A5A6*30*3535*1515*55*1010*2020*25则matrixChain为*{30,35,15,5,10,20,25}结果为*((A1*(A2*A3))*((A4*A5)*A6))*@authorzhanlingxia*/packagejuzhenliancheng;publicclassjuzhenliancheng{publicstaticvoidmain(String[]args){int[]p={30,35,15,5,10,20,25};//矩阵的维数存放于数组p中matrixMultiply(p);}//矩阵连乘publicstaticvoidmatrixMultiply(int[]p){intdimen=p.length;int[][]m=newint[dimen][dimen];//定义了存放最优值数组mint[][]s=newint[dimen][dimen];//定义了记录断开位置的数组sMatrixChain(p,m,s);System.out.println("最优乘法次数:"+m[1][dimen-1]);System.out.println("划分规则为:");traceback(s,1,dimen-1);}/*1:首先计算出m[i][i]2:然后根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。。。3:计算m[i][j]时,只要用到m[i][k]和m[k+1][j]*/publicstaticvoidMatrixChain(int[]p,int[][]m,int[][]s){intn=p.length-1;for(inti=1;i<=n;i++)m[i][i]=0;//计算单一矩阵//根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。。。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{intt=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];//更新m[i][j],s[i][j]的值if(t{m[i][j]=t;s[i][j]=k;}}}}//按算法MatrixChain计算出断点矩阵s指示的加括号方式publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}}1.3实验结论1.4心得体会算法设计真的需要逻辑思维,能得到结果挺开心的。2:最长公共子序列2.1算法设计思想(1)设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk},则若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列。若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列(2)建立递归关系:由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。用c[i][j]记录序列和的最长公共子序列的长度。其中,Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。其他情况下,由最优子结构性质可建立递归关系如下:(3)计算最优值:算法lcsLength以序列X={x1,x2…xm}和Y={y1,y2…ym}作为输入。输出两个数组c和b。其中,c[i][j]存储Xi和Yj的最长公共子序列的长度,b[i][j]记录c[i][j]的值是由哪一个子问题的解得到的,问题的最优值存放于c[m][n]中publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}elseif(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;}}returnc[m][n];}(4)构造最优解:publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}2.2程序源码最长公共子序列代码:/***下面是最长公共子序列问题的动态规划算法*char[]x={'A','B','C','D','A','B'};*char[]y={'B','D','C','A','B','A'};*打印结果为CAB*@authorzhanlingxia*/packagezuichanggonggongzixulie;publicclasszuichanggonggongzixulie{/*计算最优值c[i][j]存储Xi和Yi的最长公共子序列的长度b[i][j]记录c[i][j]的值是由最长公共子序列*/publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];//空序列最长公共子序列for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;//对角线+1for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}//和上面一样elseif(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;}}returnc[m][n];}//打印最长公共子序列publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}publicstaticvoidmain(Stringargs[]){char[]x={'A','B','C','D','A','B'};char[]y={'B','D','C','A','B','A'};int[][]b=newint[x.length+1][y.length+1];System.out.println("最长公共子序列:");intn=lcsLength(x,y,b);System.out.println();System.out.println("其长度为:"+n);System.out.println("最长公共子序列为:");lcs(x.length-1,y.length-1,x,b);}}2.3实验结论2.4心得体会:最长公共子序列比较好理解哦。做起来也相较简单多了30-1背包问题3.1算法设计思想(1)分析最优解:设(y1,y2,…,yn)是所给0-1背包问题的一个最优解,则(y2,…,yn)是下面相应子问题的一个最优解。(2)建立递归关系:设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。(3)计算最优值:publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}(4)构造最优解:publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}3.2程序源码0-1背包问题代码:/***下面是0-1的动态规划算法*v[]w[]c分别是价值、重量、和背包容量数组*m[i][j]表示有i~n个物品,背包容量为j的最大价值。*@authorzhanlingxia*/publicclassbeibao{publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}publicstaticvoidmain(String[]args){//测试int[]w={2,2,6,5,4};int[]v={6,3,5,4,6};int[][]m=newint[11][11];System.out.println("0-1背包问题最优值:");knapsack(v,w,10,m);System.out.println("0-1背包问题最优解:");int[]x=newint[w.length];traceback(m,w,10,x);for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
intt=m[i][k]+m[k+1][j]+p[i-1][k][j];
if(tm[i][j]=t;s[i][j]=k;}}}}(4)构造最优解:算法matrixChain记录了构造最优解所需的全部信息。s[i][j]=k表明计算矩阵链A[i:j]的最佳方式在矩阵Ak和Ak+1之间断开,即最优的加括号方式为(A[i:k])(A[k+1:j])。因此,从s[1][n]记录的信息可知计算A[1:n]的最优加括号方式为(A[1:s[1][n]])(A[s[1][n]+1:n])。而A[1:s[1][n]]的最优加括号方式为(A[1:s[1][s[1][n]]])(A[s[1][s[1][n]]+1:s[1][s[1][n]]])。同理可以确定A[s[1][n]+1:n]的最优加括号方式在s[s[1][n]+1][n]处断开。照此递推下去,最终可以得到A[1:n]的最优完全加括号方式,即构造出问题的一个最优解。publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}1.2程序源码矩阵连乘代码:/***下面是矩阵连乘问题的动态规划算法*假设有6个矩阵:*A1A2A3A4A5A6*30*3535*1515*55*1010*2020*25则matrixChain为*{30,35,15,5,10,20,25}结果为*((A1*(A2*A3))*((A4*A5)*A6))*@authorzhanlingxia*/packagejuzhenliancheng;publicclassjuzhenliancheng{publicstaticvoidmain(String[]args){int[]p={30,35,15,5,10,20,25};//矩阵的维数存放于数组p中matrixMultiply(p);}//矩阵连乘publicstaticvoidmatrixMultiply(int[]p){intdimen=p.length;int[][]m=newint[dimen][dimen];//定义了存放最优值数组mint[][]s=newint[dimen][dimen];//定义了记录断开位置的数组sMatrixChain(p,m,s);System.out.println("最优乘法次数:"+m[1][dimen-1]);System.out.println("划分规则为:");traceback(s,1,dimen-1);}/*1:首先计算出m[i][i]2:然后根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。。。3:计算m[i][j]时,只要用到m[i][k]和m[k+1][j]*/publicstaticvoidMatrixChain(int[]p,int[][]m,int[][]s){intn=p.length-1;for(inti=1;i<=n;i++)m[i][i]=0;//计算单一矩阵//根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。。。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{intt=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];//更新m[i][j],s[i][j]的值if(t{m[i][j]=t;s[i][j]=k;}}}}//按算法MatrixChain计算出断点矩阵s指示的加括号方式publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}}1.3实验结论1.4心得体会算法设计真的需要逻辑思维,能得到结果挺开心的。2:最长公共子序列2.1算法设计思想(1)设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk},则若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列。若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列(2)建立递归关系:由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。用c[i][j]记录序列和的最长公共子序列的长度。其中,Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。其他情况下,由最优子结构性质可建立递归关系如下:(3)计算最优值:算法lcsLength以序列X={x1,x2…xm}和Y={y1,y2…ym}作为输入。输出两个数组c和b。其中,c[i][j]存储Xi和Yj的最长公共子序列的长度,b[i][j]记录c[i][j]的值是由哪一个子问题的解得到的,问题的最优值存放于c[m][n]中publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}elseif(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;}}returnc[m][n];}(4)构造最优解:publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}2.2程序源码最长公共子序列代码:/***下面是最长公共子序列问题的动态规划算法*char[]x={'A','B','C','D','A','B'};*char[]y={'B','D','C','A','B','A'};*打印结果为CAB*@authorzhanlingxia*/packagezuichanggonggongzixulie;publicclasszuichanggonggongzixulie{/*计算最优值c[i][j]存储Xi和Yi的最长公共子序列的长度b[i][j]记录c[i][j]的值是由最长公共子序列*/publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];//空序列最长公共子序列for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;//对角线+1for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}//和上面一样elseif(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;}}returnc[m][n];}//打印最长公共子序列publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}publicstaticvoidmain(Stringargs[]){char[]x={'A','B','C','D','A','B'};char[]y={'B','D','C','A','B','A'};int[][]b=newint[x.length+1][y.length+1];System.out.println("最长公共子序列:");intn=lcsLength(x,y,b);System.out.println();System.out.println("其长度为:"+n);System.out.println("最长公共子序列为:");lcs(x.length-1,y.length-1,x,b);}}2.3实验结论2.4心得体会:最长公共子序列比较好理解哦。做起来也相较简单多了30-1背包问题3.1算法设计思想(1)分析最优解:设(y1,y2,…,yn)是所给0-1背包问题的一个最优解,则(y2,…,yn)是下面相应子问题的一个最优解。(2)建立递归关系:设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。(3)计算最优值:publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}(4)构造最优解:publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}3.2程序源码0-1背包问题代码:/***下面是0-1的动态规划算法*v[]w[]c分别是价值、重量、和背包容量数组*m[i][j]表示有i~n个物品,背包容量为j的最大价值。*@authorzhanlingxia*/publicclassbeibao{publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}publicstaticvoidmain(String[]args){//测试int[]w={2,2,6,5,4};int[]v={6,3,5,4,6};int[][]m=newint[11][11];System.out.println("0-1背包问题最优值:");knapsack(v,w,10,m);System.out.println("0-1背包问题最优解:");int[]x=newint[w.length];traceback(m,w,10,x);for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
m[i][j]=t;
s[i][j]=k;
}
(4)构造最优解:
算法matrixChain记录了构造最优解所需的全部信息。
s[i][j]=k表明计算矩阵链A[i:
j]的最佳方式在矩阵Ak和
Ak+1之间断开,即最优的加括号方式为(A[i:
k])(A[k+1:
j])。
因此,从s[1][n]记录的信息可知计算A[1:
n]的最优加括号
方式为(A[1:
s[1][n]])(A[s[1][n]+1:
n])。
而A[1:
s[1][n]]的最
优加括号方式为
(A[1:
s[1][s[1][n]]])(A[s[1][s[1][n]]+1:
s[1][s[1][n]]])。
同理可以确定A[s[1][n]+1:
n]的最优加括号方式在s[s[1][n]+1][n]处断开。
照此递推下去,最终可以得到A[1:
n]的最优完全加括号方式,
即构造出问题的一个最优解。
publicstaticvoidtraceback(int[][]s,inti,intj)
if(i==j)return;
traceback(s,i,s[i][j]);
traceback(s,s[i][j]+1,j);
System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);
1.2程序源码
矩阵连乘代码:
/**
*下面是矩阵连乘问题的动态规划算法
*假设有6个矩阵:
*A1A2A3A4A5A6
*30*3535*1515*55*1010*2020*25则matrixChain为
*{30,35,15,5,10,20,25}结果为
*((A1*(A2*A3))*((A4*A5)*A6))
*@authorzhanlingxia
*/
packagejuzhenliancheng;
publicclassjuzhenliancheng{
publicstaticvoidmain(String[]args){
int[]p={30,35,15,5,10,20,25};//矩阵的维数存放于数组p中
matrixMultiply(p);
//矩阵连乘
publicstaticvoidmatrixMultiply(int[]p){
intdimen=p.length;
int[][]m=newint[dimen][dimen];//定义了存放最优值数组m
int[][]s=newint[dimen][dimen];//定义了记录断开位置的数组s
MatrixChain(p,m,s);
System.out.println("最优乘法次数:
"+m[1][dimen-1]);
System.out.println("划分规则为:
");
traceback(s,1,dimen-1);
/*1:
首先计算出m[i][i]
2:
然后根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。
。
3:
计算m[i][j]时,只要用到m[i][k]和m[k+1][j]*/
for(inti=1;i<=n;i++)m[i][i]=0;//计算单一矩阵
//根据递归式按矩阵链长递增的方式以此计算m[i][i+1]i=1,2,3.。
m[i][j]=m[i+1][j]+p[i+1]*p[i]*p[j];
for(intk=i+1;k{intt=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];//更新m[i][j],s[i][j]的值if(t{m[i][j]=t;s[i][j]=k;}}}}//按算法MatrixChain计算出断点矩阵s指示的加括号方式publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}}1.3实验结论1.4心得体会算法设计真的需要逻辑思维,能得到结果挺开心的。2:最长公共子序列2.1算法设计思想(1)设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk},则若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列。若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列(2)建立递归关系:由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。用c[i][j]记录序列和的最长公共子序列的长度。其中,Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。其他情况下,由最优子结构性质可建立递归关系如下:(3)计算最优值:算法lcsLength以序列X={x1,x2…xm}和Y={y1,y2…ym}作为输入。输出两个数组c和b。其中,c[i][j]存储Xi和Yj的最长公共子序列的长度,b[i][j]记录c[i][j]的值是由哪一个子问题的解得到的,问题的最优值存放于c[m][n]中publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}elseif(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;}}returnc[m][n];}(4)构造最优解:publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}2.2程序源码最长公共子序列代码:/***下面是最长公共子序列问题的动态规划算法*char[]x={'A','B','C','D','A','B'};*char[]y={'B','D','C','A','B','A'};*打印结果为CAB*@authorzhanlingxia*/packagezuichanggonggongzixulie;publicclasszuichanggonggongzixulie{/*计算最优值c[i][j]存储Xi和Yi的最长公共子序列的长度b[i][j]记录c[i][j]的值是由最长公共子序列*/publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];//空序列最长公共子序列for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;//对角线+1for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}//和上面一样elseif(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;}}returnc[m][n];}//打印最长公共子序列publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}publicstaticvoidmain(Stringargs[]){char[]x={'A','B','C','D','A','B'};char[]y={'B','D','C','A','B','A'};int[][]b=newint[x.length+1][y.length+1];System.out.println("最长公共子序列:");intn=lcsLength(x,y,b);System.out.println();System.out.println("其长度为:"+n);System.out.println("最长公共子序列为:");lcs(x.length-1,y.length-1,x,b);}}2.3实验结论2.4心得体会:最长公共子序列比较好理解哦。做起来也相较简单多了30-1背包问题3.1算法设计思想(1)分析最优解:设(y1,y2,…,yn)是所给0-1背包问题的一个最优解,则(y2,…,yn)是下面相应子问题的一个最优解。(2)建立递归关系:设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。(3)计算最优值:publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}(4)构造最优解:publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}3.2程序源码0-1背包问题代码:/***下面是0-1的动态规划算法*v[]w[]c分别是价值、重量、和背包容量数组*m[i][j]表示有i~n个物品,背包容量为j的最大价值。*@authorzhanlingxia*/publicclassbeibao{publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}publicstaticvoidmain(String[]args){//测试int[]w={2,2,6,5,4};int[]v={6,3,5,4,6};int[][]m=newint[11][11];System.out.println("0-1背包问题最优值:");knapsack(v,w,10,m);System.out.println("0-1背包问题最优解:");int[]x=newint[w.length];traceback(m,w,10,x);for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
intt=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
//更新m[i][j],s[i][j]的值
if(t{m[i][j]=t;s[i][j]=k;}}}}//按算法MatrixChain计算出断点矩阵s指示的加括号方式publicstaticvoidtraceback(int[][]s,inti,intj){if(i==j)return;traceback(s,i,s[i][j]);traceback(s,s[i][j]+1,j);System.out.println("MultiplyA"+i+","+s[i][j]+"andA"+(s[i][j]+1)+","+j);}}1.3实验结论1.4心得体会算法设计真的需要逻辑思维,能得到结果挺开心的。2:最长公共子序列2.1算法设计思想(1)设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk},则若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列。若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列(2)建立递归关系:由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。用c[i][j]记录序列和的最长公共子序列的长度。其中,Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。其他情况下,由最优子结构性质可建立递归关系如下:(3)计算最优值:算法lcsLength以序列X={x1,x2…xm}和Y={y1,y2…ym}作为输入。输出两个数组c和b。其中,c[i][j]存储Xi和Yj的最长公共子序列的长度,b[i][j]记录c[i][j]的值是由哪一个子问题的解得到的,问题的最优值存放于c[m][n]中publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}elseif(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;}}returnc[m][n];}(4)构造最优解:publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}2.2程序源码最长公共子序列代码:/***下面是最长公共子序列问题的动态规划算法*char[]x={'A','B','C','D','A','B'};*char[]y={'B','D','C','A','B','A'};*打印结果为CAB*@authorzhanlingxia*/packagezuichanggonggongzixulie;publicclasszuichanggonggongzixulie{/*计算最优值c[i][j]存储Xi和Yi的最长公共子序列的长度b[i][j]记录c[i][j]的值是由最长公共子序列*/publicstaticintlcsLength(char[]x,char[]y,int[][]b){intm=x.length-1;intn=y.length-1;int[][]c=newint[m+1][n+1];//空序列最长公共子序列for(inti=1;i<=m;i++)c[i][0]=0;for(inti=1;i<=n;i++)c[0][i]=0;//对角线+1for(inti=1;i<=m;i++)for(intj=1;j<=n;j++){if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}//和上面一样elseif(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;}}returnc[m][n];}//打印最长公共子序列publicstaticvoidlcs(inti,intj,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]);}elseif(b[i][j]==2)lcs(i-1,j,x,b);elselcs(i,j-1,x,b);}publicstaticvoidmain(Stringargs[]){char[]x={'A','B','C','D','A','B'};char[]y={'B','D','C','A','B','A'};int[][]b=newint[x.length+1][y.length+1];System.out.println("最长公共子序列:");intn=lcsLength(x,y,b);System.out.println();System.out.println("其长度为:"+n);System.out.println("最长公共子序列为:");lcs(x.length-1,y.length-1,x,b);}}2.3实验结论2.4心得体会:最长公共子序列比较好理解哦。做起来也相较简单多了30-1背包问题3.1算法设计思想(1)分析最优解:设(y1,y2,…,yn)是所给0-1背包问题的一个最优解,则(y2,…,yn)是下面相应子问题的一个最优解。(2)建立递归关系:设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。(3)计算最优值:publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}(4)构造最优解:publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}3.2程序源码0-1背包问题代码:/***下面是0-1的动态规划算法*v[]w[]c分别是价值、重量、和背包容量数组*m[i][j]表示有i~n个物品,背包容量为j的最大价值。*@authorzhanlingxia*/publicclassbeibao{publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}publicstaticvoidmain(String[]args){//测试int[]w={2,2,6,5,4};int[]v={6,3,5,4,6};int[][]m=newint[11][11];System.out.println("0-1背包问题最优值:");knapsack(v,w,10,m);System.out.println("0-1背包问题最优解:");int[]x=newint[w.length];traceback(m,w,10,x);for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
//按算法MatrixChain计算出断点矩阵s指示的加括号方式
1.3实验结论
1.4心得体会
算法设计真的需要逻辑思维,能得到结果挺开心的。
2:
最长公共子序列
2.1算法设计思想
(1)
设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk},则
若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。
若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列。
若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列
由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。
用c[i][j]记录序列和的最长公共子序列的长度。
其中,Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。
当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。
故此时C[i][j]=0。
其他情况下,由最优子结构性质可建立递归关系如下:
算法lcsLength以序列X={x1,x2…xm}和Y={y1,y2…ym}作为输入。
输出两个数组c和b。
其中,c[i][j]存储Xi和Yj的最长公共子序列的长度,b[i][j]记录c[i][j]的值是由哪一个子问题的解得到的,问题的最优值存放于c[m][n]中
publicstaticintlcsLength(char[]x,char[]y,int[][]b)
intm=x.length-1;
intn=y.length-1;
int[][]c=newint[m+1][n+1];
for(inti=1;i<=m;i++)c[i][0]=0;
for(inti=1;i<=n;i++)c[0][i]=0;
for(inti=1;i<=m;i++)
for(intj=1;j<=n;j++)
if(x[i]==y[j])
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
elseif(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;
returnc[m][n];
publicstaticvoidlcs(inti,intj,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]);
elseif(b[i][j]==2)lcs(i-1,j,x,b);
elselcs(i,j-1,x,b);
2.2程序源码
最长公共子序列代码:
*下面是最长公共子序列问题的动态规划算法
*char[]x={'A','B','C','D','A','B'};
*char[]y={'B','D','C','A','B','A'};
*打印结果为CAB
packagezuichanggonggongzixulie;
publicclasszuichanggonggongzixulie{
/*计算最优值
c[i][j]存储Xi和Yi的最长公共子序列的长度
b[i][j]记录c[i][j]的值是由最长公共子序列*/
//空序列最长公共子序列
//对角线+1
//和上面一样
//和左边一样
//打印最长公共子序列
publicstaticvoidmain(Stringargs[])
char[]x={'A','B','C','D','A','B'};
char[]y={'B','D','C','A','B','A'};
int[][]b=newint[x.length+1][y.length+1];
System.out.println("最长公共子序列:
intn=lcsLength(x,y,b);
System.out.println();
System.out.println("其长度为:
"+n);
System.out.println("最长公共子序列为:
lcs(x.length-1,y.length-1,x,b);
2.3实验结论
2.4心得体会:
最长公共子序列比较好理解哦。
做起来也相较简单多了
30-1背包问题
3.1算法设计思想
设(y1,y2,…,yn)是所给0-1背包问题的一个最优解,则
(y2,…,yn)是下面相应子问题的一个最优解。
设所给0-1背包问题的子问题
的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。
由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。
publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m)
intn=v.length-1;
intjMax=Math.min(w[n]-1,c);
for(intj=0;j<=jMax;j++)
m[n][j]=0;//当w[n]>j有m[n][j]=0
//m[n][j]表示只有n物品,背包的容量为j时的最大价值
for(intj=w[n];j<=c;j++)
m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]
//递规调用求出m[][]其它值,直到求出m[0][c]
for(inti=n-1;i>=1;i--)
jMax=Math.min(w[i]-1,c);
m[i][j]=m[i+1][j];
for(intj=w[i];j<=c;j++)
m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
m[0][c]=m[1][c];
if(c>=w[0])
m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);
System.out.println(+m[0][c]);
publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x)
{//根据最优值求出最优解
intn=w.length-1;
for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}3.2程序源码0-1背包问题代码:/***下面是0-1的动态规划算法*v[]w[]c分别是价值、重量、和背包容量数组*m[i][j]表示有i~n个物品,背包容量为j的最大价值。*@authorzhanlingxia*/publicclassbeibao{publicstaticvoidknapsack(int[]v,int[]w,intc,int[][]m){intn=v.length-1;intjMax=Math.min(w[n]-1,c);for(intj=0;j<=jMax;j++)m[n][j]=0;//当w[n]>j有m[n][j]=0//m[n][j]表示只有n物品,背包的容量为j时的最大价值for(intj=w[n];j<=c;j++)m[n][j]=v[n];//当w[n]<=j有m[n][j]=v[n]//递规调用求出m[][]其它值,直到求出m[0][c]for(inti=n-1;i>=1;i--){jMax=Math.min(w[i]-1,c);for(intj=0;j<=jMax;j++)m[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[0][c]=m[1][c];if(c>=w[0])m[0][c]=Math.max(m[0][c],m[1][c-w[0]]+v[0]);System.out.println(+m[0][c]);}publicstaticvoidtraceback(int[][]m,int[]w,intc,int[]x){//根据最优值求出最优解intn=w.length-1;for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}publicstaticvoidmain(String[]args){//测试int[]w={2,2,6,5,4};int[]v={6,3,5,4,6};int[][]m=newint[11][11];System.out.println("0-1背包问题最优值:");knapsack(v,w,10,m);System.out.println("0-1背包问题最优解:");int[]x=newint[w.length];traceback(m,w,10,x);for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
if(m[i][c]==m[i+1][c])
x[i]=0;
else{
x[i]=1;
c-=w[i];
x[n]=(m[n][c]>0)?
1:
0;
3.2程序源码
0-1背包问题代码:
*下面是0-1的动态规划算法
*v[]w[]c分别是价值、重量、和背包容量数组
*m[i][j]表示有i~n个物品,背包容量为j的最大价值。
publicclassbeibao
for(inti=0;iif(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}x[n]=(m[n][c]>0)?1:0;}publicstaticvoidmain(String[]args){//测试int[]w={2,2,6,5,4};int[]v={6,3,5,4,6};int[][]m=newint[11][11];System.out.println("0-1背包问题最优值:");knapsack(v,w,10,m);System.out.println("0-1背包问题最优解:");int[]x=newint[w.length];traceback(m,w,10,x);for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
publicstaticvoidmain(String[]args)
//测试
int[]w={2,2,6,5,4};
int[]v={6,3,5,4,6};
int[][]m=newint[11][11];
System.out.println("0-1背包问题最优值:
knapsack(v,w,10,m);
System.out.println("0-1背包问题最优解:
int[]x=newint[w.length];
traceback(m,w,10,x);
for(inti=0;iSystem.out.print(x[i]);}}3.3实验结论3.4心得体会深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。不过还是有点成就感的
3.3实验结论
3.4心得体会
深夜了,我被0-1背包问题折磨了一晚上,总算搞定了;从伪代码到代码的历程好艰辛。
不过还是有点成就感的
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1