Python prep 随想练习-Day2

Day2-part1

Graphs and Breadth-First Search 图和广度优先搜索

问题描述

在这里介绍了图,以及实现了广度优先搜索,具体详解决的问题如图所示。
在这里插入图片描述

图的表示方法

图的表示方法通过字典来实现
字典的key值对应图中的每个点。value值对应连接的其余节点。

在这里插入图片描述

广度优先搜索

广度优先搜索的目的是什么? 寻找最短路径
广度搜索的实现方法是什么?逐层完成搜索实现。
在这里插入图片描述
在这里插入图片描述
一层一层进行寻找,直到找到目标点。
如何实现对图的广度搜索呢? S:存储已经出现过的节点的集合 T:一颗N叉树 Q:一个便于进进出出的队列
下面我们来看一下广度搜索的伪代码吧。

在这里插入图片描述
上面的伪代码核心在于哪里呢?是不是在于队列方面的应用?

如果我们的队列不为空?
我们就不断从队列的左端pop一个节点出来,判断他的值是否是target,如果是target那就说明已经找到了节点,随后返回我们的最短路径就好了。
但是如果不是target,那么针对所有的子节点,全部放入队列里,重复上述操作。
看一下流程图吧!

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

G = { 'A' : [ 'B', 'J', 'Me' ],
         'B' : [ 'A' ],
         'C' : [ 'D', 'P' ],
         'D' : [ 'C', 'O' ],
         'E' : [ 'F', 'J', 'K' ],
         'F' : [ 'E', 'M' ],
         'G' : [ 'K', 'S', 'Ed' ],
         'H' : [ 'O', 'U' ],
         'Me': [ 'A', 'I', 'N', 'V' ],
         'I' : [ 'Me', 'Q' ],
         'J' : [ 'A', 'E', 'L', 'Q', 'W' ],
         'K' : [ 'E', 'G' ],
         'L' : [ 'J', 'W' ],
         'M' : [ 'E', 'S', 'T' ],
         'N' : [ 'Me', 'V' ],
         'O' : [ 'H', 'D' ],
         'P' : [ 'C', 'U' ],
         'Q' : [ 'I', 'J', 'X', 'Y' ],
         'R' : [ 'Ed' ],
         'S' : [ 'G', 'M', 'Y', 'Z' ],
         'T' : [ 'M' ],
         'U' : [ 'H', 'P' ],
         'V' : [ 'Me', 'N' ],
         'W' : [ 'J', 'L' ],
         'X' : [ 'Q', 'Y' ],
         'Y' : [ 'Q', 'S', 'X', 'Z' ],
         'Ed': [ 'G', 'R', 'Z' ],
         'Z' : [ 'S', 'Y', 'Ed' ] }
class tree:
    class treenode:
        def __init__(self,val=0,children=[]):
            self.val=val
            self.children=[]
            self.next=None
    def __init__(self):
        self.root=None
    def add(self,cur,v):
        cur.children.append(v)
def BFS(G,root,target):
    s=[]
    T=tree()
    s.append(root)
    node=tree.treenode(val=root)
    T.root=node
    from collections import deque
    que=deque([T.root])
    while que:
        a=que.popleft()
        if a.val==target:
            result=[]
            while(a!=None):
                result.append(a.val)
                a=a.next
            return list(reversed(result))
        for v in G[a.val]:
            if v not in s:
                s.append(v)
                node=tree.treenode(val=v)
                node.next=a
                T.add(node,a)
                que.append(node)
print(DFS(G,'Me','Ed'))

有点困了,就先放在这里吧!

看一下这段代码,第一遍看的时候包含 resultnext 的内容先不用看。
先看一下其它部分的代码,其实也就是对伪代码的实现。定义了一颗N叉树,定义了一个存放 已经出现过的节点的集合s。
将这个N叉树的根节点设置为 value=‘Me’的树节点,然后利用队列的性质完成遍历。针对每一层,逐步把他们都放入Tree的children中,同时也把他们都放在que队列的最末端。
这样实现遍历,最后得到搜索结果。
resultnext是做什么用的呢?是为了展示搜索的最短路径!
这里我想的是通过链表来解决问题,他不是一个正向的链表,而是一个反向的链表,让下一个节点指向上一个节点。
在这里插入图片描述
这样就能够确保找到target目标点之后,可以通过不断的进行next,返回到root根节点。宝贝自己看一下能不能想的明白呢?

图论这里就这样喽。

Day 2-part 2

Intro to Dynamic Programming 初识动态规划

问题描述

斐波那契数列问题,棒料切割问题和有向图问题,在这里对你来说应该是小菜一碟了!

斐波那契数列问题

这里我直接放代码了

def f(n):
	if n<2:
		return n
	else:
		return f(n-1)+f(n-2)
def fib(n):
	dp=[0]*(n+1)
	if n==0:
		return dp[0]
	dp[1]=1
	for i in range(2,n+1):
		dp[i]=dp[i-1]+dp[i-2]
	return dp[n]
def fib(n):
	return int((pow((1+5**0.5)/2,n)-pow((1-5**0.5)/2,n))/5**0.5)

分别对应了三种方法,自己回忆一下吧。

棒料切割问题

你有一根长度为10的棒料,你应该以什么方法划分,才能够得到棒料划分的最大价值!在这里插入图片描述
这里因为是引入动态规划的一节,所以ppt里面的代码写的沾点让人看不懂了哦。
我们用动态规划来做。
[1 ] 确定dp数组(dp table)以及下标的含义
[2 ] 确定递推公式
[3 ] dp数组如何初始化
[4 ] 确定遍历顺序
[5 ] 举例推导dp数组

1. 确定dp数组
dp数组很显然应该是一维数组,长度对应的是这根棒子的总长度。dp数组存储的内容是什么呢?dp数组存储的是当前棍棒长度,通过划分可以存放的最大价值
对初始化进行考虑,根据dp数组的定义,在最开始,还没有考虑划分问题。那么dp[ i ]肯定全部是0
在这里插入图片描述
2.确定递推公式

dp[ j ]=max(dp[ j ],dp[ j -method[ i ][ 0 ]]+method[ i ][ 1 ])
自己画一下图想一下这个公式是什么意思吧!
因为可以用一种划分方法重复划分,所以这就是一个完全背包问题!

在这里插入图片描述

method=[
    [1,1],
    [2,5],
    [3,8],
    [4,9]
]
def cut(n):
    dp=[0]*(n+1)
    for i in range(len(method)):
        for j in range(method[i][0],n+1):
            dp[j]=max(dp[j],dp[j-method[i][0]]+method[i][1])
    return dp[n]
print(cut(10))

有向图问题

在这里插入图片描述
以这张图为例,有向图是什么呢?第一,只能沿着箭头通行;第二,走每条路都需要花费一定的代价。我们想解决的问题是,形成一个矩阵,便于我们查阅从点A到点B的最小代价。
针对这个图,我们用二维邻接矩阵来表示。
A[ i , j ]表示从点 i 走到点 j 的代价。极大值代表两者之间无通路,走不通。
在这里插入图片描述

max_value=float('inf')
A[0]=[
	[0,max_value,max_value,1],
	[2,0,4,5],
	[max_value,max_value,0,3],
	[max_value,7,1,0]
]

针对A[ i ][ j ]为从i到j的最短路径应该是:
A[ i ][ j ]=min(A[ i ][ u ]+w[ u ][ j ]),就是说从i点到j点的最短路径,一定是从i点到u点的最短路径加上从u点到j点的路径,最开始看这个公式其实很难理解,我们借助图来看一下这些公式。
A[ k ][ s ][ t ]=min(A[ k-1 ][ s ][ t ], A[ k-1 ][ s ][ k ]+A[ k-1 ][ k ][ t ])

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

借助代码实现一下:

max_value=float('inf')
A=[[]]
A[0]=[
	[0,max_value,max_value,1],
	[2,0,4,5],
	[max_value,max_value,0,3],
	[max_value,7,1,0]
]
def find(A):
	n=len(A[0][0])
	for i in range(1,n+1):
		A.append(A[0])
		for j in range(n):
			for k in range(n):
				A[i][j][k]=min(A[i-1][j][k],A[i-1][j][i-1]+A[i-1][i-1][k])
	return A
find(A)
print(A[len(A[0][0])])

这一部分的内容又算是学完了,包含很多图的问题,我应该讲的时候会和你argue很久。但是你能学会就好了,针对每个算法,自己理解下,动手画画,让他们成为你自己的东西!我相信你一定可以的。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值