爱问知识人 爱问教育 医院库

写一篇《论算法设计中的分治与增量》的学术论文1500字

首页

写一篇《论算法设计中的分治与增量》的学术论文1500字


        

提交回答
好评回答
  • 2008-11-16 14:13:00
      一、动态规划的基本思想在比较基本的算法设计思想里,动态规划是比较难于理解,难于抽象的一种,但是却又十分重要。动态规划的实质是分治思想和解决冗余,因此它与分治法和贪心法类似,它们都是将问题的实例分解为更小的、相似的子问题,但是动态规划又有自己的特点。
      贪心法的当前选择可能要依赖于已经作出的选择,但不依赖于还未做出的选择和子问题,因此它的特征是由顶向下,一步一步地做出贪心选择,但不足的是,如果当前选择可能要依赖子问题的解时,则难以通过局部的贪心策略达到全局最优解。相比而言,动态规划则可以处理不具有贪心实质的问题。
      在用分治法解决问题时,由于子问题的数目往往是问题规模的指数函数,因此对时间的消耗太大。动态规划的思想在于,如果各个子问题不是独立的,不同的子问题的个数只是多项式量级,如果我们能够保存已经解决的子问题的答案,而在需要的时候再找出已求得的答案,这样就可以避免大量的重复计算。
      由此而来的基本思路是,用一个表记录所有已解决的子问题的答案,不管该问题以后是否被用到,只要它被计算过,就将其结果填入表中。比较感性的说,其实动态规划的思想是对贪心算法和分治法的一种折衷,它所解决的问题往往不具有可爱的贪心实质,但是各个子问题又不是完全零散的,这时候我们用一定的空间来换取时间,就可以提高解题的效率。
      二、动态规划的基本步骤动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值(最大值或最小值)的那个解。设计一个动态规划算法,通常可以按以下几个步骤进行:(1)找出最优解的性质,并刻画其结构特征。
      (2)递归地定义最优值。(3)以自底向上的方式计算出最优值。(4)根据计算最优值时得到的信息,构造一个最优解。其中(1)——(3)步是动态规划算法的基本步骤。在只需要求出最优值的情形,步骤(4)可以省去。若需要求出问题的一个最优解,则必须执行步骤(4)。
      此时,在步骤(3)中计算最优值时,通常需记录更多的信息,以便在步骤(4)中,根据所记录的信息,快速构造出一个最优解。三、典型的动态规划举例——矩阵连乘问题作为经典的动态规划算法举例,矩阵连乘问题很好地展现了动态规划的特点和实用价值。给定n个矩阵{A1,A2,。
      。。,An},其中Ai与Ai+1是可乘的,i=1,2,。。。n-1。现在要计算这n个矩阵的连乘积。由于矩阵的乘法满足结合律,所以通过加括号可以使得计算矩阵的连乘积有许多不同的计算次序。然而采用不同的加扩号方式,所需要的总计算量是不一样的。若A是一个p*q矩阵,B是一个q*r矩阵,则其乘积C=AB是一个p*r矩阵。
      如果用标准算法计算C,总共需要pqr次数乘。现在来看一个例子。A1,A2,A3分别是10*100,100*5和5*50的矩阵。如果按照((A1A2)A3)来计算,则计算所需的总数乘次数是10*100*5+10*5*50=7500。如果按照(A1(A2A3))来计算,则需要的数乘次数是100*5*50+10*100*50=75000,整整是前者的10倍。
      由此可见,在计算矩阵连乘积时,不同的加括号方式所导致的不同的计算对计算量有很大的影响。如何确定计算矩阵连乘积A1A2,。。。,An的一个计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少便成为一个问题。对于这个问题,穷举法虽然易于入手,但是经过计算,它所需要的计算次数是n的指数函数,因此在效率上显得过于低下。
      现在我们按照动态规划的基本步骤来分析解决这个问题,并比较它与穷举法在时间消耗上的差异。(1)分析最优解的结构。现在,将矩阵连乘积AiAi+1。。。Aj简记为A[i:j]。对于A[1:n]的一个最优次序,设这个计算次序在矩阵Ak和Ak+1之间将矩阵链断开(1<=k<n),那么完全加括号的方式为((A1。
      。。Ak)(Ak+1。。。An))。依此次序,我们应该先分别计算A[1:k]和A[k+1:n],然后将计算结果相乘得到A[1:n],总计算量为A[1:k]的计算量加上A[k+1:n]的计算量,再加上A[1:k]和A[k+1:n]相乘的计算量。
      通过反证法可以证明,问题的关键特征在于,计算A[1:n]的一个最优次序所包含的计算矩阵子链A[1:k]和A[k+1:n]的次序也是最优的。因此,矩阵连乘积计算次序问题的最优解包含着其子问题的最优解。这种最优子结构性质是该问题可以用动态规划解决的重要特征。
      (2)建立递归关系定义最优值。设计算A[i:j](1<=i<=j<=n)所需的最少数乘次数为m[i][j],则原问题的最优值为m[1][n]。而且易见,当i=j时,m[i][j]=0。根据上述最优子结构性质,当i<j时,若计算A[i:j]的最优次序在Ak和Ak+1之间断开,可以定义m[i][j]=m[i][k]+m[k+1][j]+pi-1*pk*pj(其中,Ai的维数为pi-1*pi)。
      从而有:当i=j时,m[i][j]=0。当i<j时,m[i][j]=min{m[i][k]+m[k+1][j]+pi-1*pk*pj} (i<=k<j)。除此之外,若将对应于m[i][j]的断开位置记为s[i][j],在计算出最优值m[i][j]后,可以递归地由s[i][j]构造出相应的最优解。
      (3)计算最优值。如果直接套用m[i][j]的计算公式,进行简单的递归计算需要耗费指数计算时间。然而,实际上不同的子问题的个数只是n的平方项级(对于1<=i<=j<=n不同的有序对(i,j)对应于不同的子问题)。用动态规划解决此问题,可依据其递归式以自底向上的方式进行计算。
      在计算过程中,保存已解决的子问题答案。每个子问题只计算一次,而在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法。下面给出计算m[i][j]的动态规划算法:void matrixChain (int * p, int n, int * * m, int * * s){ 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; } } }}算法首先设定m[i][i]=0(i=1,2,。
      。。,n)。然后再根据递归式按矩阵链长的递增方式依此计算出各个m[i][j],在计算某个固定的m[i][j]时,只用到已计算出的m[i][k]和m[k+1][j]。稍加分析就可以得出,这个算法以O(n^2)的空间消耗大大降低了时间复杂度,计算时间的上界为O(n^3)。
      (4)构造最优解。通过以上算法的计算,我们知道了要计算所给矩阵连乘积所需的最少数乘次数,但是还不知道具体应该按照什么顺序来做矩阵乘法才能达到这个次数。然而,s[i][j]已经存储了构造最优解所需要的足够的信息。从s[1][n]记录的信息可知计算A[1:n]的最优加括号方式为(A[1:s[1][n]])(A[s[1][n]+1:n])。
      同理,每个部分的最优加括号方式又可以根据数组s的相应元素得出。照此递推下去,最终可以确定A[1:n]的最优完全加括号方式,即构造出问题的一个最优解。四、结语本文简单介绍了动态规划的基本思想、步骤和简单例题。以后笔者还会给大家介绍更多的例子,以及由动态归划衍生出来的备忘录方法,使大家即使在不能清晰地分析出问题子结构的从属关系时,仍能够避免不必要的重复计算,快速地解决问题。
      一、分治算法 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。 分治法解题的一般步骤: (1)分解,将要解决的问题划分成若干规模较小的同类问题; (2)求解,当子问题划分得足够小时,用较简单的方法解决; (3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
       当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。
      如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。下面通过实例加以说明。 【例1】 [找出伪币] 给你一个装有1 6个硬币的袋子。1 6个硬币中有一个是伪造的,并且那个伪造的硬币比真的硬币要轻一些。
      你的任务是找出这个伪造的硬币。为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。比较硬币1与硬币2的重量。假如硬币1比硬币2轻,则硬币1是伪造的;假如硬币2比硬币1轻,则硬币2是伪造的。
      这样就完成了任务。假如两硬币重量相等,则比较硬币3和硬币4。同样,假如有一个硬币轻一些,则寻找伪币的任务完成。假如两硬币重量相等,则继续比较硬币5和硬币6。按照这种方式,可以最多通过8次比较来判断伪币的存在并找出这一伪币。 另外一种方法就是利用分而治之方法。
      假如把1 6硬币的例子看成一个大的问题。第一步,把这一问题分成两个小问题。随机选择8个硬币作为第一组称为A组,剩下的8个硬币作为第二组称为B组。这样,就把1 6个硬币的问题分成两个8硬币的问题来解决。第二步,判断A和B组中是否有伪币。可以利用仪器来比较A组硬币和B组硬币的重量。
      假如两组硬币重量相等,则可以判断伪币不存在。假如两组硬币重量不相等,则存在伪币,并且可以判断它位于较轻的那一组硬币中。最后,在第三步中,用第二步的结果得出原先1 6个硬币问题的答案。若仅仅判断硬币是否存在,则第三步非常简单。无论A组还是B组中有伪币,都可以推断这1 6个硬币中存在伪币。
      因此,仅仅通过一次重量的比较,就可以判断伪币是否存在。 现在假设需要识别出这一伪币。把两个或三个硬币的情况作为不可再分的小问题。注意如果只有一个硬币,那么不能判断出它是否就是伪币。在一个小问题中,通过将一个硬币分别与其他两个硬币比较,最多比较两次就可以找到伪币。
      这样,1 6硬币的问题就被分为两个8硬币(A组和B组)的问题。通过比较这两组硬币的重量,可以判断伪币是否存在。如果没有伪币,则算法终止。否则,继续划分这两组硬币来寻找伪币。假设B是轻的那一组,因此再把它分成两组,每组有4个硬币。称其中一组为B1,另一组为B2。
      比较这两组,肯定有一组轻一些。如果B1轻,则伪币在B1中,再将B1又分成两组,每组有两个硬币,称其中一组为B1a,另一组为B1b。比较这两组,可以得到一个较轻的组。由于这个组只有两个硬币,因此不必再细分。比较组中两个硬币的重量,可以立即知道哪一个硬币轻一些。
      较轻的硬币就是所要找的伪币。 【例2】在n个元素中找出最大元素和最小元素。我们可以把这n个元素放在一个数组中,用直接比较法求出。算法如下: void maxmin1(int A[],int n,int *max,int *min) { int i; *min=*max=A[0]; for(i=2;i < n;i++) { if(A > *max) *max= A; if(A < *min) *min= A; } } 上面这个算法需比较2(n-1)次。
      能否找到更好的算法呢?我们用分治策略来讨论。 把n个元素分成两组: A1={A[1],。。。,A[int(n/2)]}和A2={A[INT(N/2)+1],。。。,A[N]} 分别求这两组的最大值和最小值,然后分别将这两组的最大值和最小值相比较,求出全部元素的最大值和最小值。
      如果A1和A2中的元素多于两个,则再用上述方法各分为两个子集。直至子集中元素至多两个元素为止。 例如有下面一组元素:-13,13,9,-5,7,23,0,15。用分治策略比较的过程如下: 图中每个方框中,左边是最小值,右边是最大值。从图中看出,用这种方法一共比较了10次,比直接比较法的14次减少4次,即约减少了1/3。
      算法如下: void maxmin2(int A[],int i,int j,int *max,int *min) /*A存放输入的数据,i,j存放数据的范围,初值为0,n-1,*max,int *min 存放最大和最小值*/ { int mid,max1,max2,min1,min2; if (j==i) {最大和最小值为同一个数;return;} if (j-1==i) {将两个数直接比较,求得最大会最小值;return;} mid=(i+j)/2; 求i~mid之间的最大最小值分别为max1,min1; 求mid+1~j之间的最大最小值分别为max2,min2; 比较max1和max2,大的就是最大值; 比较min1和min2,小的就是最小值; } 利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等因素,而二分法,由于其划分的简单和均匀的特点,是经常采用的一种有效的方法,例如二分法检索。
      运用分治策略解决的问题一般来说具有以下特点: 1、原问题可以分解为多个子问题,这些子问题与原问题相比,只是问题的规模有所降低,其结构和求解方法与原问题相同或相似。 2、原问题在分解过程中,递归地求解子问题,由于递归都必须有一个终止条件,因此,当分解后的子问题规模足够小时,应能够直接求解。
       3、在求解并得到各个子问题的解后,应能够采用某种方式、方法合并或构造出原问题的解。 不难发现,在分治策略中,由于子问题与原问题在结构和解法是的相似性,用分治方法解决的问题,大都采用了递归的形式。在各种排序方法中,如归并排序、堆排序、快速排序等,都存在有分治的思想。
      

    李***

    2008-11-16 14:13:00

其他答案

类似问题

  • 院校信息 相关知识

  • 教育培训
  • 教育科学
  • 教育考试

相关推荐

正在加载...
最新资料 推荐信息 热门专题 热点推荐
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200

热点检索

  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
返回
顶部
帮助 意见
反馈

确定举报此问题

举报原因(必选):