动态规划

标题教材(版本)试题
钢条切割算法导论(3)18-1
矩阵链乘法算法导论(3)16-2-64,19-1-62
最长公共子序列算法导论(3)17-2-62,15-2
最优二叉查找树算法导论(3)
0-1背包软件设计师教程(5)16-1-62,19-2
装配线调度算法导论(2)17-1-62

适用于动态规划的问题:

  1. 最优子结构.
  2. 重叠子问题.

备忘法:

记录子问题结果.

回溯法:

由结果重建过程.

“大多数人都是这样:如果你告诉他们事情的经过,他们就会告诉你接下来的结果。他们默默地对事情的经过进行综合分析,通过取舍,就能得出结论。只有少数人,如果你把结果告诉了他们,他们就能通过他们内在的意识,推断出造成这种结果的每个步骤是什么。这就是在我说到’回溯推理’或者’分析的方法’时,所指的那种能力。”——《血字的研究》

钢条切割

钢条切割
递推式(双侧切割):
递推式
递推式(单侧切割):
递推式

带备忘的自顶向下法:

	var r=[],s=[]
	function topDownCutRod(p,n){
		if(!r[n]){
			r[n]=p[n]
			s[n]=0
			for(var i=1;i<=n/2;i++){
				var tmp=topDownCutRod(p,i)+topDownCutRod(p,n-i)
				if(tmp>r[n]){
					r[n]=tmp
					s[n]=i
				}
			}
		}
		return r[n]
	}
	var p=[0,1,5,8,9,10,17,17,20,24,30]
	topDownCutRod(p,8)
	console.log(r,s)

自底向上法:

	var r=[],s=[]
	function bottomUpCutRod(p,n){
		for(var i=1;i<=n;i++){
			r[i]=p[i]
			s[i]=0
			for(var j=1;j<=i/2;j++){
				var tmp=r[j]+r[i-j]
				if(tmp>r[i]){
					r[i]=tmp
					s[i]=j
				}
			}
		}
		return r[n]
	}
	var p=[0,1,5,8,9,10,17,17,20,24,30]
	bottomUpCutRod(p,8)
	console.log(r,s)

回溯法重建切割过程:

	function traceBackwardsCutRod(n){
		var t=[]
		while(s[n]){
			t.push(s[n])
			n-=s[n]
		}
		t.push(n-s[n])
		console.log(t)
	}
	traceBackwardsCutRod(8)

最长公共子序列

最长公共子序列
递推式:
递推式

自底向上法:

  var c=[]
  function bottomUpLCS(x,y,m,n){
	  for(var i=0;i<=m;i++){
		  c[i]=[0]
	  }
	  for(var i=1;i<=n;i++){
		  c[0][i]=0
	  }
	  for(var i=1;i<=m;i++){
		  for(var j=1;j<=n;j++){
			  if(x[i-1]==y[j-1]){
				  c[i][j]=c[i-1][j-1]+1
			  }else{
				  c[i][j]=Math.max(c[i][j-1],c[i-1][j])
			  }
		  }
	  }
  }
  var x='ABCADAB',y='BDCABA'
  var m=x.length,n=y.length
  bottomUpLCS(x,y,m,n)
  console.log(c)

回溯法重建LCS:

  var z=[]
  function traceBackwardsLCS(m,n){
	  for(var i=m,j=n;i>0&&j>0;){
		  if(c[i][j]==c[i][j-1]){
			  j--
		  }else if(c[i][j]==c[i-1][j]){
			  i--
		  }else{
			  z.unshift(x[i-1])
			  i--
			  j--
		  }
	  }
  }
  traceBackwardsLCS(m,n)
  console.log(z)

0-1背包

0-1背包
递推式:
递推式
带备忘的自顶向下法:

  var c=[]
  function topDownKnapsack(v,w,i,j){
	  if(!c[i]){
		  c[i]=[]
	  }
	  if(!c[i][j]){
		  if(i==0||j==0){
			  c[i][j]=0
		  }else{
			  c[i][j]=topDownKnapsack(v,w,i-1,j)
			  if(j-w[i-1]>=0){
				  var temp=topDownKnapsack(v,w,i-1,j-w[i-1])+v[i-1]
				  if(c[i][j]<temp){
					  c[i][j]=temp
				  }
			  }
		  }
	  }
	  return c[i][j]
  }
  var v=[4,5,10,11,13]
  var w=[3,4,7,8,9]
  var t=17
  topDownKnapsack(v,w,v.length,t)
  console.log(c)

回溯法重建装包过程:

  var s=[]
  function traceBackwardsKnapsack(v,w,i,j){
	  if(i>0){
		  if(c[i][j]!=c[i-1][j]&&c[i][j]>0){
			  s[i-1]=1
			  traceBackwardsKnapsack(v,w,i-1,j-w[i-1])
		  }else{
			  s[i-1]=0
			  traceBackwardsKnapsack(v,w,i-1,j)
		  }
	  }
  }
  traceBackwardsKnapsack(v,w,v.length,t)
  console.log(s)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值