回顾动态规划

对于动态规划,一直感觉会了,但又不怎么会,难点的题也做不到自己完成,今天再总结一下:

首先动态规划到底是干啥的?
现在想来,应该是用数组记录递归中的结果【第一次接触动态规划就是斐波那契了吧
然后动态规划要做到每次选最佳方案【OPT】

怎么得到这个OPT呢?
对于下一个数,我们可以选择、也可以不选,如果选择,那么OPT就是前一个不冲突的OPT+这个数;如果不选,那么OPT不会变,还是之前的OPT。这里举个栗子:

对一数组{1,2,4,1,7,8,3},选择不相邻的数,使其相加所得和最大

计算OPT(i):
OPT(0)=arr[0]
OPT(1)=max(arr[0],arr[1])
之后的最佳方案:
选择第i个,那么OPT(i)=OPT(i-2)+arr[i]
不选择第i个,OPT(i)=OPT(i-1)
注:通常前两个值是特殊值,不过特殊情况特殊考虑

递归写法:

arr=[1,2,4,1,7,8,3]
def opt(arr,i):
	if i==0:
		return arr[0]
	elif i==1:
		return max(arr[0],arr[1])
	else:
		A=opt(arr,i-2)+arr[i]
		B=opt(arr,i-1)
		return max(A,B)

动规写法:
将中间结果存在数组opt中

import numpy as np#创建数组用的包
def dp_opt(arr):
	opt=np.zeros(len(arr))
	opt[0]=arr[0]
	opt[1]=max(arr[0],arr[1])
	for i in range(2,len(arr)):
		A=opt[i-2]+arr[i]
		B=opt[i-1]
		opt[i]=max(A,B)
	return opt[len(arr)-1]

对一数组{1,2,4,1,7,8,3},判断是否有两数相加为特定数12?

剪枝,从后往前选或不选
sub(arr[6],12),【i=6,s=12】表示arr[6]前相加可以为12就行,对于arr[6]选或者不选
选为:sub(arr[i-1],s-arr[i])------>sub(arr[5],9)
不选为:sub(arr[i-1],s)------>sub(arr[5],12)
这两个有一个满足返回true
特殊值

  • 当第二项参数为0,说明已经符合题意,返回true
  • 当只剩下一个数字arr[0]时,判断arr[0]是否等于此时的第二项:
    相等则返回true
  • 当arr[i]大于第二项,不用考虑选的情况,因为不能加出个负数

递归实现:

def sub(arr,i,s):
	if s==0:
		return True
	elif i==0:
		return arr[0]==s
	elif arr[i]>s:
		return sub(arr,i-1,s)
	else:
		A=sub(arr,i-1,s)
		B=sub(arr,i-1,s-arr[i])
		return A or B

动规实现:
用二维数组存储:[arr[i],s]

import numpy as np
def dp_sub(arr,su):
	#二维数组设计
	sub=zeros((len(arr),s+1),dtype=bool)#含s=0
	sub[:,0]=True#每一行第0列【s==0】为True
	sub[0,:]=False#第0行除arr[0]==s外,都为False
	sub[0,arr[0]]=True
	for i in range(1,len(arr)):
		for s in range(1,su+1):
			if arr[i]>s:
				sub[i,s]=sub[i-1,s]
			else:
				A=sub[i-1,s]
				B=sub[i-1,s-arr[i]]
				sub[i,s]=A or B
	r,c=sub.shape#获得行数、列数
	return sub[r-1,c-1]
	

关键点:
找出口【特殊值】
分析选或不选的公式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值