Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。
输入格式:
第一行一个整数 n,表示可供选用的食材种类数。
接下来 n 行,每行 2 个整数 s**i 和 b**i ,表示第 i 种食材的酸度和苦度。
输出格式:
一行一个整数,表示可能的总酸度和总苦度的最小绝对差。
python复制代码
n=int(input())
a=[]
b=[]
for i in range(n):
x,y=list(map(int,input().split()))
a.append(x)
b.append(y)
# 初始化:记录 酸程度 和 苦程度
suan=1
ku=0
def bfs(depth):
global suan
global ku
global mins
for i in range(depth,n):
suan=suan*a[i]
ku=ku+b[i]
mins=min(mins,abs(suan-ku))
bfs(i+1)
suan=suan/a[i]
ku=ku-b[i]
mins=abs(a[0]-b[0])
bfs(0)
print(int(mins))
--------------------------------------
输入:
4
1 7
2 6
3 8
4 9
输出:
1
--------------------------------------
n,m=list(map(int,input().split()))
pool = [list(map(int, input().split())) for _ in range(n)]
# 记录是否走过:0表示没有走过;1表示走过
visit = [[0] * m for _ in range(n)]
# 位移偏量:上下左右
direction = [[0,1],[0,-1],[1,0],[-1,0]]
ans=0
def bfs(sx, sy):
water = 0 # 初始化当前连通区域的水量为0
queue = [[sx, sy]] # 创建一个【队列】,用于BFS,初始时将起始格子加入队列
while queue: # 当队列不为空时,继续搜索
x, y = queue.pop(0) # 弹出队列的第一个元素(如:sx,sy),获取其坐标【当前正在访问的格子】
water += pool[x][y] # 将当前格子的水量加入到water中
for dx, dy in direction: # 遍历四个方向
xx, yy = x + dx, y + dy # 计算新坐标
if xx < n and xx>=0 and yy < m and yy>=0: # 判断新坐标是否在网格范围内
# 如果新坐标对应的格子未被访问过且水量不为0
if visit[xx][yy]==0 and pool[xx][yy] != 0:
visit[xx][yy] = 1 # 标记为已访问
queue.append([xx, yy]) # 将新坐标加入队列,继续搜索
return water # 返回当前连通区域的水量
for i in range(n):
for j in range(m):
# 若这个格子没有做过 并且 对应值不为0
if visit[i][j]==0 and pool[i][j] != 0:
visit[i][j]=1
ans=max(ans,bfs(i,j))
print(ans)
------------------------------------------
输入:
3 3
1 2 0
3 4 0
0 0 5
输出:
10
------------------------------------------
n = int(input())
a=[list(input()) for _ in range(n)]
# 记录是否走过:0表示没有走过;1表示走过
visited = [[0]*n for _ in range(n)]
# 位移偏量:上下左右
direction = [[0,1],[0,-1],[1,0],[-1,0]]
# 记录岛屿的数量
count=0
def dfs(x,y):
global flag # 表示是否会被淹掉:0表示会被淹,1表示不会被淹
ans=0 # 岛屿格子数
queue = [[x, y]] # 创建一个【队列】,用于BFS,初始时将起始格子加入队列
while queue:
x, y = queue.pop(0) # 弹出队列的第一个元素(如:sx,sy),获取其坐标【当前正在访问的格子】
# 【当前正在访问的格子】不会被淹没
if a[x - 1][y] == '#' and a[x + 1][y] == '#' and a[x][y - 1] == '#' and a[x][y + 1] == '#':
flag = 1
for dx, dy in direction: # 遍历四个方向
xx, yy = x + dx, y + dy # 计算新坐标
if a[xx][yy]=='#' and visited[xx][yy]==0: # 判断新坐标是否在网格范围内
visited[xx][yy] = 1 # 标记为已访问
queue.append([xx, yy]) # 将新坐标加入队列,继续搜索
for i in range(n):
for j in range(n):
if visited[i][j] == 0 and a[i][j] == '#':
visited[i][j]=1
flag=0
dfs(i,j)
if flag==0: # 被淹掉
count+=1
print(count)
---------------------------------------------
输入:
7
.......
.##....
.##....
....##.
..####.
...###.
.......
输入:
1 # 被淹掉的岛屿数量为1
---------------------------------------------
n, m = map(int, input().split())
# 邻接矩阵【二维数组】
grid=[list(map(int,input().split())) for _ in range(n)]
# 位移偏量:上下左右
direction = [[0, 1], [1, 0], [0, -1], [-1, 0]]
# 记录是否走过:0表示没有走过;1表示走过
visited = [[0] * m for _ in range(n)]
num=0
def bfs(x,y):
queue=[[x,y]]
while queue:
x1,y1=queue.pop(0)
if grid[x1][y1]==0:
return
for dx,dy in direction:
xx=x1+dx
yy=y1+dy
# 判断新坐标是否在网格范围内
if xx < n and xx>=0 and yy < m and yy>=0:
# 如果下一个位置是未访问过的陆地,则标记为已访问,并继续深度优先搜索
if grid[xx][yy]==1 and visited[xx][yy]==0:
visited[xx][yy]=1
queue.append([xx,yy])
for i in range(n):
for j in range(m):
if visited[i][j]==0 and grid[i][j]==1:
num += 1 # 发现新的陆地区域,计数器加1
bfs(i,j)
print(num)
-----------------------------------
输入:
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出:
3
-----------------------------------
四、搜索问题
1、扫雷游戏
扫雷游戏是一款十分经典的单机小游戏。
在 n 行 m 列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。
玩家翻开一个非地雷格时,该格将会出现一个数字------提示周围格子中有多少个是地雷格。
游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。
现在给出 n 行 m 列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。
注:一个格子的周围格子包括其:左上、上、右上、左、右、左下、下、右下八个方向上与之直接相邻的格子。
基本思想:
python复制代码
n,m=list(map(int,input().split()))
# 存放信息
g=[input() for _ in range(n)]
# 位移偏量
dx = [-1, -1, -1, 0, 0, 1, 1, 1]
dy = [-1, 0, 1, -1, 1, -1, 0, 1]
def check(x,y):
cnt=0
# 遍历八个方向(位移偏量)
for i in range(0,8):
a=x+dx[i] # 各个方向上对应的x
b=y+dy[i] #各个方向上对应的 y
# 边界性
if a<0 or a>n-1 or b<0 or b>m-1:
continue
if g[a][b]=='*':
cnt+=1
return cnt
# 遍历每一个点,搜索附近的地雷数
for i in range(0,n):
for j in range(0,m):
if g[i][j]=='*':
print('*',end='')
else:
ans=check(i,j)
print(ans,end='')
if i<n-1:
print()
-----------------------------------
输入:
3 3
*??
???
?*?
输出:
*10
221
1*1
-----------------------------------
n,m=map(int,input().split())
a=[list(map(int,input().split())) for i in range(n)]
x1,y1,x2,y2=list(map(int,input().split()))
# 从 0 开始的索引,因此将这些坐标减去 1 以转换为索引
x1, y1, x2, y2 = x1 - 1, y1 - 1, x2 - 1, y2 - 1
# 记录是否走过:0表示没有走过;1表示走过
visit = [[0] * m for _ in range(n)]
# 位移偏量:上下左右
direction = [[0,1],[0,-1],[1,0],[-1,0]]
def bfs():
queue = [[x1, y1, 0]]
while queue:
x,y,z=queue.pop(0)
# 到达目的地
if x==x2 and y==y2:
return z
# 遍历四个方向
for dx,dy in direction:
# 计算新坐标
xx = x + dx
yy = y + dy
# 判断新坐标是否在网格范围内 并且 新坐标为道路(值为1) 并且 标志是未走过的(值为0)
if xx < n and xx >= 0 and yy < m and yy >= 0 and a[xx][yy]==1 and visit[xx][yy]==0:
visit[xx][yy]=1 # 已经访问了,标记为1
queue.append([xx,yy,z+1])
return -1
print(bfs())
-------------------------------------------
输入:
5 5
1 0 1 1 0
1 1 0 1 1
0 1 0 1 1
1 1 1 1 1
1 0 0 0 1
1 1 5 5
输出:
8
-------------------------------------------
3、马的遍历
题目描述:
有一个 n ×m 的棋盘,在某个点 (x ,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式:
输入只有一行四个整数,分别为 n ,m ,x ,y。
输出格式:
一个 n ×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1)。
python复制代码
n,m,x,y=list(map(int,input().split()))
# 从 0 开始的索引,因此将这些坐标减去 1 以转换为索引
x,y=x-1,y-1
# 棋盘
board = [[-1]*m for _ in range(n)]
board[x][y]=0 # 【起始位置】设置为0
# 记录是否走过:0表示没有走过;1表示走过
visit = [[0] * m for _ in range(n)]
visit[x][y] = 1 # 【标记起点】为已访问
# 位移偏量:马走日字格
direction = [[-2,-1],[-2,1],[-1,-2],[-1,2],[1,-2],[1,2],[2,-1],[2,1]]
def bfs(x1,y1):
queue=[[x1,y1,0]]
while queue:
x, y, z = queue.pop(0)
for dx,dy in direction:
xx=x+dx
yy=y+dy
if xx < n and xx >= 0 and yy < m and yy >= 0 and visit[xx][yy] == 0:
visit[xx][yy] = 1 # 标记为已访问
if board[xx][yy] == -1 or board[xx][yy] > z + 1: # 更新最短步数
board[xx][yy] = z + 1
queue.append([xx, yy, z + 1]) # 加入队列继续搜索
return -1
bfs(x, y) # 从起点开始搜索
# 输出结果矩阵
for i in range(n):
for j in range(m):
print(board[i][j], end=' ')
print() # 换行输出每一行的结果
--------------------------------------------------
输入:
3 3 1 1
输出:
0 3 2
3 -1 1
2 1 4
--------------------------------------------------