【算法模板】优先搜索与组合枚举

排列数字

给定一个整数n,将数字1~n排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有排列方法输出。

输入格式

共一行,包含一个整数 n。

输出格式

按字典序输出所有排列方案,每个方案占一行。

数据范围

1\leq n\leq 7

输入样例

3

输出样例

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

AC Code: 

'''
# #AC Code(排列数字)# #
'''
import itertools
n = int(input())
que = [x for x in range(1, n + 1)]
for temp in itertools.permutations(que):
    print(" ".join(map(str, temp)))

递归实现组合型枚举

从 1∼n 这 n个整数中随机选出 m个,输出所有可能的选择方案。

输入格式

两个整数 n ,m在同一行用空格隔开。

输出格式

按照从小到大的顺序输出所有方案,每行 11 个。

首先,同一行内的数升序排列,相邻两个数用一个空格隔开。

其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。

数据范围

n> 0,

0\leq m\leq n,

n+(n-m)\leq 25

输入样例

5 3

输出样例

1 2 3 
1 2 4 
1 2 5 
1 3 4 
1 3 5 
1 4 5 
2 3 4 
2 3 5 
2 4 5 
3 4 5 

AC Code: 

'''
# #AC Code(递归实现组合枚举)# #
NOTE: 从 1∼n 这 n个整数中随机选出 m个,输出所有可能的选择方案。
'''
def dfs(x):
    if x == m + 1:
        for i in range(1, m + 1):
            print(p[i],end=" ")
        print()
        return 
    
    for val in range(p[x-1] + 1, n - m + x + 1):
        p[x] = val
        dfs(x + 1)
    
n, m = map(int, input().split())
p = [0] * (m + 1)
dfs(1)

BFS走迷宫

给定一个 n × m 的二维整数数组,用来表示一个迷宫,数组中只包含01,其中0表示可以走的路,1表示不可以通过的墙壁。
最初,有一个人位于左上角(1,1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角(r, m)处,至少需要移动多少次。
数据保证(1,1)处和(n, m)处的数字为0,且一定至少存在一条通路。
输入格式
第─行包含两个整数n和m。
接下来n行,每行包含m个整数(0或1),表示完整的二维数组迷宫。
输出格式
输出一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1 ≤ n, m ≤ 100。
输入样例:

5 5
01000
01010
00000
01110
00010

输出样例: 

8

AC Code

'''
# #AC Code(bfs走迷宫)# #
'''
def bfs():
    st[0][0] = 0
    # 1. 初始化队列
    queue = [(0,0)]    
    dx = [-1, 0 , 1, 0]    # !!!网格遍历的技巧:左,上,右,下
    dy = [0, 1, 0, -1]

    # 2. while queue不为空 
    while queue:
        # 3. 队顶元素出队
        x,y = queue.pop(0)
        # 4. 遍历,满足条件的入队
        for i in range(4):
            a = x + dx[i]
            b = y + dy[i]
            if a>=0 and a=0 and b

树的重心

给定一颗树,树中包含n个结点〔编号1~n)和n一1条无向边。

请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

输入格式
第—行包含整数n,表示树的结点数。
接下来n―1行,每行包含两个整数α和b,表示点α和点b之间存在—条边。
输出格式
输出一个整数m,表示将重心删除后,剩余各个连通块中点数的最大值。
数据范围
1 < n < 10**5。
输入样例

9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6

输出样例

4

AC Code

'''
# #AC Code(树的重心)# #
NOTE:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
'''
from collections import defaultdict, deque
def dfs(u):
   
    global res    # !!!出错:这里要声明res为全局变量
    st[u] = True
    size = 0    # 用来存储以u为根的所有子树的节点的最大值(不包含u节点(根节点本身))
    sumNode = 0    # 存储以u为根节点的所有子节点数(不包含u节点(根节点本身))
   
    for v in graph[u]:
        if not st[v]:
            # 入栈前函数 ↑
            s = dfs(v)   # 返回u节点的以v为根节点的子树的节点数
            # 出栈后函数 ↓(递归的含义)
            sumNode += s
            size = max(size, s)
   
    size = max(size, n-sumNode - 1)    # 减1:表示减去u节点本身
    res = min(res, size)

    return sumNode + 1    # 加1:表示包含i节点的总节点数

# 1. 输入示例(n个节点的无向图)
n = int(input())
graph = defaultdict(list)
for i in range(n - 1):
    u, v = map(int, input().split())
    graph[u].append(v)
    graph[v].append(u)
# 2. 初始化状态数组
st = [False] * (n + 1)
res = n
dfs(1) # 可以从任何<=n的结点开始 始终都会遍历所有的结点
print(res)

滑雪

给定一个RC列的矩阵,表示—个矩形网格滑雪场。
已知矩阵中第i行第j列的点表示滑雪场的第i行第j列区域的高度。一个人从滑雪场中的某个区域内出发,每次可以向上下左右任意一个方向滑动一个单位距离。

当然,一个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度。下面给出一个矩阵作为例子:

1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

在给定矩阵中,一条可行的滑行轨迹为24-17-2一1.
在给定矩阵中,最长的滑行轨迹为25-24-23-...-3-2一1,沿途共经过25个区域。
现在给定你一个二维矩阵表示滑雪场各区域的高度,请你找出在该滑雪场中能够完成的最长滑雪轨迹,并输出其长度(可经过最大区域数).
输入格式
第一行包含两个整数RC
接下来R行,每行包含C个整数,表示完整的二维矩阵。
输出格式
输出1个整数,表示可完成的最长滑雪长度。
数据范围
1 ≤ R,C ≤ 300.
0 ≤ 矩阵中整数 ≤  10000
输入样例:

5 5
1 2 3 4 5 
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

输出样例:

25

AC Code 


'''
# #AC Code(滑雪)# #
'''
from collections import defaultdict, deque

dx = [-1, 0, 1, 0]
dy = [0, -1, 0, 1]
    
def dfs(x, y):
    if f[x][y] != -1:
        return f[x][y]
    f[x][y] = 1
    for i in range(4):
        prex = x + dx[i]
        prey = y + dy[i]
        if prex >= 0 and prex < n and prey >= 0 and prey < m and g[x][y] > g[prex][prey]:
            f[x][y] = max(f[x][y], dfs(prex, prey) + 1)
    return f[x][y]
    
n, m = map(int, input().split())
f = [[-1 for _ in range(m)] for _ in range(n)]
g = []
for _ in range(n):
    g.append(list(map(int, input().split())))

res = 0
for i in range(n):
    for j in range(m):
        res = max(res, dfs(i, j))
print(res)

你可能感兴趣的:(算法,深度优先)