1.带分数
from itertools import permutations
num = int(input())
ans = 0
for n in range(1, num + 1):
if '0' in str(n) or len(set(list(str(n)))) != len(str(n)):
# 判断是否有0和重复数字
continue
diff = num - n # 剩下的数(后面的分数应该算出来的值)
s = '123456789'
for i in str(n):
s = s.replace(i, '') # 去掉已经使用过的数
for length in range(1, len(s) // 2 + 1): # 分母的长度
for i in permutations(s, length): # 长度为length的分母的全排列
fenzi = str(int(''.join(i)) * diff) # 计算分子
if len(fenzi) == len(s) - length: # 判断计算出来的分子是否合法
if set(list(fenzi)) == set(list(s)) - set(list(''.join(i))):
ans += 1
print(ans)
2.李白打酒
def dfs(a, b, c): # 遇到店的剩余次数,遇到花的剩余次数,剩余酒的数量
ans = 0
if a == 0 and b == 0 and c == 1:
return 1
if a > 0:
ans += dfs(a - 1, b, c * 2) # 遇到店
if b > 0:
ans += dfs(a, b - 1, c - 1) # 遇到花
return ans
print(dfs(5, 9, 2))
num = 0
def dfs(a, b, c):
if a == 0 and b == 0 and c == 1:
global num
num += 1
return
if a > 0:
dfs(a-1, b, c*2)
if b > 0:
dfs(a, b-1, c-1)
dfs(5, 9, 2)
print(num)
3.第39级台阶
lis = [[-1] * 39 for _ in range(39)]
def dfs(n, s): # n代表阶梯数,s代表步数
if n > 39:
return 0
elif n == 39:
return 1 if s % 2 == 0 else 0
if lis[n][s] != -1:
return lis[n][s]
else:
ans = dfs(n + 1, s + 1) + dfs(n + 2, s + 1)
lis[n][s] = ans
return ans
print(dfs(0, 0))
4.穿越雷区
n = int(input())
m = [input().split(' ') for _ in range(n)]
visit = [[False] * n for _ in range(n)] # 记录是否访问过
step = [(0, -1), (0, 1), (-1, 0), (1, 0)]
queue = [(0, 0, 0)] # 存三个值:坐标、当前移动的步数
while queue:
y, x, t = queue.pop(0)
if m[y][x] == 'B':
print(t)
break
for dy, dx in step:
ny = y + dy
nx = x + dx
if -1 < nx < n and -1 < ny < n:
if not visit[ny][nx] and m[y][x] != m[ny][nx]:
# 没有访问过并且不是连续走相同的区域
queue.append((ny, nx, t+1))
visit[y][x] = True
if not queue:
print(-1)
5.迷宫
m = '''01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000'''
m = m.split('\n')
visit = [[False] * 50 for _ in range(30)]
visit[0][0] = True
step = [(1, 0, 'D'), (0, -1, 'L'), (0, 1, 'R'), (-1, 0, 'U')]
queue = [(0, 0, -1, 0)] # 坐标、父节点在path中的下标、走的方向对应的字母
path = []
while queue:
y, x, _, _ = cur = queue.pop(0)
path.append(cur)
if cur[:2] == (29, 49):
# 走到终点
temp = []
i = len(path) - 1
while i > 0: # 沿着之前标记的父节点将路径取出
temp.append(path[i][3])
i = path[i][2]
temp.reverse() # 反转,因为取出来的路径是反的
print(''.join(temp))
break
for dy, dx, dir in step: # 往上下左右走一步
ny, nx = y+dy, x+dx # 下一步到达的位置
if -1 < nx < 50 and -1 < ny < 30 and m[ny][nx] == '0' and not visit[ny][nx]:
# 判断是否越界、迷宫该位置是否能走、是否已经走过
queue.append((ny, nx, len(path)-1, dir)) # 将下一步添加到队列中,len(path)-1 是添加到节点的父节点在path中的下标
visit[ny][nx] = True # 标记已经访问过
6.跳马
a, b, c, d = map(int, input().split(' '))
step = [(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]
visit = [[False]*8 for _ in range(8)]
queue = [(a, b, 0)] # 坐标、步数
while queue:
y, x, t = queue.pop(0)
if y == c and x == d:
print(t)
break
for dy, dx in step:
ny = y + dy
nx = x + dx
if -1 < ny < 8 and -1 < nx < 8 and not visit[ny][nx]:
queue.append((ny, nx, t+1))
visit[ny][nx] = True
if not queue:
print(-1)
7.路径之谜
n = int(input())
nums = [list(map(int, input().split(' '))) for _ in range(2)] # 第一行是上面的,第二行是左面的
visit = [[False]*n for _ in range(n)]
visit[0][0] = True
ans = [0]
record = [[0]*n for _ in range(2)]
record[0][0] = record[1][0] = 1
step = [(0, -1), (0, 1), (-1, 0), (1, 0)]
def dfs(y, x):
if y == n-1 and x == n-1 and record == nums:
print(' '.join(map(str, ans)))
return
for dy, dx in step:
ny = y + dy
nx = x + dx
if -1 < ny < n and -1 < nx < n and not visit[ny][nx]:
ans.append(ny*n + nx)
visit[ny][nx] = True
record[0][nx] += 1
record[1][ny] += 1
dfs(ny, nx)
ans.pop()
visit[ny][nx] = False
record[0][nx] -= 1
record[1][ny] -= 1
dfs(0, 0)
8.未名湖边的烦恼
m, n = map(int, input().split(' '))
record = [[-1]*(n+1) for _ in range(m+1)]
def dfs(a, b): # 还鞋、借鞋
if a == b == 0:
return 1
if record[a][b] != -1:
ans = record[a][b]
else:
ans = 0
if a > 0:
ans += dfs(a-1, b)
if 0 < b <= a:
ans += dfs(a, b-1)
record[a][b] = ans
return ans
print(dfs(m, n))
9.大臣的旅费
cnt=0
node=0
def dfs(v,k): #进行dfs搜索
global cnt
global node
global vis
if k>cnt:
cnt=k
node=v
for i in range(len(E[v])):
if vis[E[v][i][0]]==False: #没访问过的点都进行一次dfs
vis[E[v][i][0]]=True #进行标记
dfs(E[v][i][0],k+E[v][i][1])
vis[E[v][i][0]]=False #回溯
n=int(input())
E=[[]for i in range(n+1)]
vis=[False for i in range(n+1)]
for i in range(n-1):
x,y,z=map(int,input().split())
E[x].append((y,z))
E[y].append((x,z)) #将各个点进行连接,用列表数组的方式进行
vis[1]=True
dfs(1,0) #找到距离1最远的点node
vis[1]=False
cnt=0
vis[node]=True
dfs(node,0) #从node出发,找到最远的点,就是所要求的最远距离
res=0
for i in range(1,cnt+1):
res+=i+10
print(res)
10.2n皇后问题
def conflict(queen_lis, new_queen):
"""判断棋子是否符合规则"""
for index, queen in enumerate(queen_tup):
if abs(new_queen - queen) in (len(queen_tup) - index, 0): # 判断表达式:垂直距离和水平距离
# 列数之差是否等于行数之差,或者列数之差为零
# 注意,len(queen_tup)是行数。因为第一行不进入循环,所以,这里的行数要比len出来的值加一,也就是,len(queen_tup)如果等于3,那么对应的是第四行
# 对应的,index也是要加一的。
return False
return True
def arrange_queen(num, queen_lis=[]):
"""
:param num:棋盘的的行数,当然数值也等于棋盘的列数
:param queen_tup: 设置一个空队列,用于保存符合规则的棋子的信息
"""
for new_queen in range(num): # 遍历一行棋子的每一列
if conflict(queen_tup, new_queen): # 判断是否冲突
if len(queen_tup) == num - 1: # 判断是否是最后一行
yield [new_queen] # yield关键字,返回当前的位置。
else:
# 若果不是最后一行,递归函数接着放置棋子
for result in arrange_queen(num, queen_lis + [new_queen]):# 结果的迭代
yield [new_queen] + result # 这个是每个函数最终的地方。
for i in arrange_queen(4):
print(i)