第36次CCF计算机软件能力认证 python 参考代码
- 题目列表
- 1. 移动
- 2. 梦境巡查
- 3. 缓存模拟
- 4. 跳房子
题目列表
第36次CCF计算机软件能力认证
1. 移动
思路分析:针对每个查询,按照指令逐步修改机器人的位置,并且检查是否越界。
n, k = map(int, input().split())
for i in range(k):
word = input().split()
x = int(word[0])
y = int(word[1])
move = word[2]
for char in move:
if char == 'f' and y < n:
y += 1
elif char == 'b' and y > 1:
y -= 1
elif char == 'l' and x > 1:
x -= 1
elif char == 'r' and x < n:
x += 1
print(x, y)
优化思路:
- 在执行移动指令时,可以直接对每个指令进行判断和更新位置,而无需每次都写重复的条件判断。
- 可以通过构建一个简单的字典来映射每个指令
(f, b, l, r)
的对应变化。f
对应(0, 1)
表示y
增加 1(向上)。b
对应(0, -1)
表示y
减少 1(向下)。l
对应(-1, 0)
表示x
减少 1(向左)。r
对应(1, 0)
表示x
增加 1(向右)。
n, k = map(int, input().split())
# 方向映射字典
direction_map = {
'f': (0, 1), # 向上移动:y+1
'b': (0, -1), # 向下移动:y-1
'l': (-1, 0), # 向左移动:x-1
'r': (1, 0) # 向右移动:x+1
}
for _ in range(k):
x, y, move = input().split()
x, y = int(x), int(y)
for char in move:
dx, dy = direction_map[char]
# 计算新的位置
new_x, new_y = x + dx, y + dy
# 检查是否越界,更新位置
if 1 <= new_x <= n and 1 <= new_y <= n:
x, y = new_x, new_y
print(x, y)
2. 梦境巡查
模拟一遍。
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
for i in range(n):
w = a[0]
sum_a = a[0]
sum_b = 0
for j in range(n):
sum_a += a[j+1]
if j != i:
sum_b += b[j]
w = max(w, sum_a - sum_b)
print(w, end=' ')
3. 缓存模拟
有计算机组成原理的味道在!
大模拟,按照思路来写的,读和写部分的代码可能有点重复。
from collections import deque
n, N, q = map(int, input().split())
groups = [deque(maxlen=n) for _ in range(N)]
dirty = [] # 维护一个被修改过的内存块列表
for _ in range(q):
o, a = map(int, input().split())
g = a//n%N # 该内存块所在组号
print("o is:", o, "a is: ", a,"g is:",g, "groups[g] has :", groups[g], "dirty has:", dirty)
if o == 0:
if a in groups[g]: # 读命中
groups[g].remove(a) # 更新位置
groups[g].appendleft(a)
else: # 读未命中,将该内存块读入缓存
if len(groups[g]) < n: # 该组存在空余位置
groups[g].appendleft(a) # 插入该内存块
else: # 该组不存在空余位置
old = groups[g].pop() # 挤掉队列最后的内存块
if old in dirty: # 查找 dirty 中是否存在该内存块
dirty.remove(old) # 若存在则从 dirty 中删去该内存块
print(1, old) # 并输出 写该内存块
groups[g].appendleft(a) # 插入该内存块
# 输出 读内存块
print(0, a)
elif o == 1:
dirty.append(a) # 将该内存块添加到 dirty 中
if a in groups[g]: # 写命中
groups[g].remove(a) # 更新位置
groups[g].appendleft(a)
else: # 写未命中,将该内存块读入缓存
if len(groups[g]) < n: # 该组存在空余位置
groups[g].appendleft(a) # 插入该内存块
else: # 该组不存在空余位置
old = groups[g].pop() # 挤掉队列最后的内存块
if old in dirty: # 查找 dirty 中是否存在该内存块
dirty.remove(old) # 若存在则从 dirty 中删去该内存块
print(1, old) # 并输出 写该内存块
groups[g].appendleft(a) # 插入该内存块
# 输出 读内存块
print(0, a)
4. 跳房子
思路分析:动态规划,通过 res[i]
记录从起点到达第 i
格子的最少跳跃次数。对于每个格子,更新其后面的跳跃范围,并计算更新后的最少跳跃次数。
import math
n = int(input())
back = list(map(int, input().split()))
jump = list(map(int, input().split()))
# res 列表维护 到达第 index 个格子需要的最少跳跃次数
res = [math.inf for _ in range(n)]
res[0] = 0
# 遍历 jump 列表
for index in range(n):
value = jump[index]
# print(index, value)
# 遍历 back 列表的 index, min(index+value,n)
for i in range(index+1 ,min(n,index+value+1)):
backi = back[i]
# print("i:", i, "backi:", backi)
if i-backi >= 0 and res[i-backi] > res[index]+1:
res[i-backi] = res[index]+1
# print("res[",i-backi,"]:", res[i-backi])
if res[n-1] != math.inf:
print(res[n-1])
else:
print(-1)
BFS 遍历:
- 从第一个格子 0 开始,依次探索当前格子能跳到的所有格子(跳跃的范围由
k[i]
控制),并计算每个格子跳跃后的目标位置。 - 如果当前目标位置是有效的且通过当前格子的跳跃次数可以更新目标格子,更新
res
数组,并将目标位置加入queue
。 queue
队列:用于 BFS 搜索,记录当前能够跳跃到的格子。
from collections import deque
def jump_game(n, a, k):
# 使用一个数组来记录到达每个格子所需的最少跳跃次数
res = [float('inf')] * n
res[0] = 0 # 起始点跳跃次数为0
# BFS 队列,存储每个格子的位置
queue = deque([0]) # 从第0个格子开始
while queue:
current = queue.popleft()
# 跳跃的最大范围是从 current+1 到 min(current+k[current], n-1)
for next_pos in range(current + 1, min(current + k[current], n) + 1):
if next_pos < n: # 确保 next_pos 是有效的索引
target_pos = next_pos - a[next_pos]
# 如果目标位置合法且可以通过当前格子的跳跃次数更新
if 0 <= target_pos < n and res[target_pos] > res[current] + 1:
res[target_pos] = res[current] + 1
queue.append(target_pos)
# 返回到达最后一个格子的跳跃次数,如果没有到达,返回 -1
return res[n - 1] if res[n - 1] != float('inf') else -1
# 读取输入
n = int(input()) # 格子的数量
a = list(map(int, input().split())) # 各格子的后退值
k = list(map(int, input().split())) # 各格子的最大跳跃范围
# 输出最少跳跃次数
print(jump_game(n, a, k))