【废物研究生零基础刷算法】DFS与递归(二)习题
- 电脑硬件
- 2025-09-15 17:54:02

文章目录 P2089烤鸡(指数)P1088火星人(全排列)P1149火柴棒等式(指数+预处理)P2036 PERKET(指数)棋盘问题(全排列)数的划分(组合)【迷宫问题】【最大连通块问题】P1596 [USACO10OCT] Lake Counting S P2089烤鸡(指数)
说明:对于100%的数据,n小于等于5000
N = 30 n = int(input()) arr = [0] * N # 存储当前方案,索引 1 到 10 res = 0 memo = [] # 存储所有方案的列表 def dfs(x, sum_val): # x 表示当前配料,sum_val 表示当前总和 global res if sum_val > n: # 超过 n,剪枝 return if x > 10: # 填满 10 种配料 if sum_val == n: # 总和恰好为 n res += 1 scheme = [arr[i] for i in range(1, 11)] # 复制当前方案 memo.append(scheme) return for i in range(1, 4): # 每种配料选 1 到 3 arr[x] = i dfs(x + 1, sum_val + i) # 累加 i 到 sum_val dfs(1, 0) # 从第 1 种配料开始,总和为 0 print(res) # 输出方案总数 if res > 0: for scheme in memo: # 输出每种方案 print(" ".join(map(str, scheme))) P1088火星人(全排列)import sys sys.setrecursionlimit(10**9) n = int(input()) m = int(input()) mars = [0] + list(map(int, input().split())) ans = [0 for _ in range(n+1)] st = [0 for _ in range(n+1)] cnt = 0 # 通常会用深度优先搜索(DFS)生成所有可能的排列,并通过一个计数器 cnt 来跟踪当前是第几个排列。cnt 的具体作用是: # 每当 DFS 生成一个完整的排列时,cnt 增加 1。 # 通过 cnt,我们可以知道当前排列在字典序中的位置(第几个) def dfs(x): global cnt if x > n: cnt += 1 if cnt == m + 1: # 说明我们已经生成了从火星人排列开始的第 M 个后续排列(包括火星人排列本身后的第 M 个 print(*ans[1:]) exit() return i = 1 while i <= n: if cnt == 0: i = mars[x] if not st[i]: st[i] = 1 ans[x] = i dfs(x + 1) st[i] = 0 ans[x] = 0 i += 1 dfs(1) P1149火柴棒等式(指数+预处理) N = 1010 n = int(input()) n -= 4 huo_1000 = [0] * N huo = [6, 2, 5, 5, 4, 5, 6, 3, 7, 6] nums = huo + huo_1000 arr = [0] * N # 存放当前状态 count = 0 def col(x): if nums[x] > 0: return nums[x] else: sumFire = 0 while x: sumFire += nums[int(x % 10)] x /= 10 return sumFire def dfs(x, sum): global count if sum > n: return if x > 3: if arr[1] + arr[2] == arr[3] and sum == n: count += 1 print(*arr[0:4]) return for i in range(0, 1000): # 每个位置遍历火柴的数量 arr[x] = i dfs(x + 1, sum + col(i)) arr[x] = 0 dfs(1, 0) print(count) # 程序从 dfs(1, 0) 开始递归搜索,这意味着它首先尝试确定A的值,然后是B,最后是C。如果从arr[0]开始,则可能意味着不同的设计选择,但基于上述逻辑,这里的实现直接跳过了arr[0],从arr[1]开始代表A。 P2036 PERKET(指数) # 最大配料数量 N = 50 # 读取配料数量 n = int(input()) # 用于标记每种配料的选择状态,0 未考虑,1 选择,2 不选择 st = [0] * (N + 1) # arr是记录当前状态,如果没有输出的话不需要 # 初始化最小差值为一个较大的值 res = float('inf') # 存储每种配料的酸度 acid = [0] # 存储每种配料的苦度 bitter = [0] # 读取每种配料的酸度和苦度 for i in range(n): line = list(map(int, input().split())) acid.append(line[0]) bitter.append(line[1]) def dfs(x): global res # 当考虑完所有配料时 if x > n: # 标记是否选择了至少一种配料 has_ingredient = False acid_sum = 1 bitter_sum = 0 # 遍历所有配料 for i in range(1, n + 1): if st[i] == 1: has_ingredient = True acid_sum *= acid[i] bitter_sum += bitter[i] # 只有选择了至少一种配料时才更新结果 if has_ingredient: res = min(res, abs(acid_sum - bitter_sum)) return # 选择当前配料 st[x] = 1 dfs(x + 1) # 不选择当前配料 st[x] = 2 dfs(x + 1) # 恢复状态 st[x] = 0 # 从索引 1 开始进行深度优先搜索 dfs(1) print(res) 棋盘问题(全排列) def dfs(x, count, n, k, g, st): global res if count == k: # 已经放置了 k 个棋子 res += 1 return if x >= n: # 超出棋盘行数(从 0 到 n-1) return # 尝试在当前行 x 放置棋子 for i in range(n): if not st[i] and g[x][i] == '#': # 列未使用且当前位置是棋盘区域 st[i] = True dfs(x + 1, count + 1, n, k, g, st) st[i] = False # 也可以选择当前行不放棋子,直接跳到下一行 dfs(x + 1, count, n, k, g, st) # 主程序 while True: line1 = list(map(int, input().split())) n = line1[0] k = line1[1] if n == -1 and k == -1: break # 初始化 g = [] # 棋盘 res = 0 # 结果 st = [False] * n # 标记每列是否使用 # 读取棋盘 for _ in range(n): g.append(list(input())) dfs(0, 0, n, k, g, st) print(res) 数的划分(组合) line1 = list(map(int, input().split())) n = line1[0] k = line1[1] arr = [0] * n res = 0 def dfs(x, start, num_sum): global res if num_sum > n: return if x == k: if num_sum == n: res += 1 return for i in range(start, n): # 题目要求每份不能为空,即最小值为1,而且为了保证是递增序列要从start开始 arr[i] = i dfs(x + 1, i, num_sum + i) arr[i] = i dfs(0, 1, 0) print(res) 【迷宫问题】
习题
N = 20 line1 = list(map(int, input().split())) w = line1[0] h = line1[1] g = [] for i in range(h): line = list(input()) g.append(line) # # for row in g: # print(row) dx = [-1, 0, 1, 0] dy = [0, 1, 0, -1] st = [[False for _ in range(N)] for _ in range(N)] res = 0 def dfs(x, y): global res for i in range(4): a = x + dx[i] b = y + dy[i] if a < 0 or a >= h or b < 0 or b >= w: continue if g[a][b] == '#': continue if st[a][b]: continue st[a][b] = True res += 1 dfs(a, b) for i in range(h): for j in range(w): if g[i][j] == '@': dfs(i, j) # res+=1 print(res) 【最大连通块问题】P1596 [USACO10OCT] Lake Counting S line1 = list(map(int, input().split())) n = line1[0] m = line1[1] st = [[False for _ in range(m)] for _ in range(n)] # 存放状态,被选择过or没被选择过 g = [] for row in range(n): line = list(input()) g.append(line) res = 0 # for row in g: # print(row) dx = [1, 1, 1, 0, 0, -1, -1, -1] dy = [-1, 0, 1, 1, -1, 1, 0, -1] # 最好配对记住 def dfs(x, y): for i in range(8): a = x + dx[i] b = y + dy[i] if a < 0 or b < 0 or a >= n or b >= m: continue if g[a][b] == '.': continue if st[a][b]: continue st[a][b] = True dfs(a, b) for i in range(n): for j in range(m): if g[i][j] == 'W' and st[i][j] == False: dfs(i, j) res += 1 print(res)【废物研究生零基础刷算法】DFS与递归(二)习题由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【废物研究生零基础刷算法】DFS与递归(二)习题”
上一篇
基于单片机的GPS定位系统设计