1. 修栅栏(连续k个子序列和最小)
输入:
7 3
1 2 6 1 1 7 1输出:
3说明:
从第三个位置开始拔栏杆拔掉的长度最小为8
分析:
- 这个题是变相的求解长度为k的连续子序列和最小时,序列的起始位置
- 需要注意的是:随着遍历,不断变化的变量有:_sum:长度为k 的子序列的和, _min:只有符合条件时,才会变化
1 import sys 2 3 if __name__ == '__main__': 4 n, k = map(int, sys.stdin.readline().split(" ")) 5 h = list(map(int, sys.stdin.readline().split(" "))) 6 7 _min = sum(h[:k]) 8 flag = 1 9 _sum = _min 10 for i in range(k, n): 11 _sum = _sum + h[i] - h[i - k] 12 if _sum < _min: 13 _min = _sum 14 flag = i - k + 2 15 print(flag)
2. 小Q玩游戏
输入:
2
4 6
X...XX
...XX.
.X..X.
......
1 6
2 2
9 47
....X.X.X.X...X..X.....X..X..X..X....X.X...X..X
XX..X...X.........X...X...X..X.XX......X...X...
..XX...X.......X.....X.....X.XX..X.....X..XX...
.X...XX....X...X.......X.X...X......X.X.X......
X......X..X.XXX....X...X.X.XX..X.......X....X.X
....XX.X...X.XXX.X..XX.XXX...XXX..XX.X.X.XX..XX
.........X...X.XXXX...XX.XX....XX..X...X....X..
.............X....XXXX....X.X...XX.XX.X.X..X...
.X......X.....X......X......X.X.X..X.......XXX.
2 34
7 30
输出:
YES
NO
分析:
- 题中:“.” 表示没有被破坏的方块,“X”:表示已经被破坏的方块。已经被破坏的方块走一次就会碎掉(不能再走了),没有被破坏的方块可以走2次。 为了方便,在输入时做一个映射,maps = {".":2, ”X":1 }
- “.”:可以走两次, “X”:只能走一次(不能再走了):即,当走到该位置时,如果 符号是“.” ,将“.” 更换成“X”, 继续走;如果符号是“X”, 终止不能再走了。即,2 能走, 1不能走。
1 import sys 2 import numpy as np 3 4 # 全局变量:上右下左,横纵坐标的偏移量 5 dx, dy = [-1, 0, 1, 0], [0, 1, 0, -1] 6 7 # 找路径 8 def find(n, m, sig, begin, end, x, y): 9 # 走到最后一个格子,并且踩碎 10 sig[x][y] -= 1 11 if x == end[0]-1 and y == end[1]-1 and sig[x][y] == 1: return True 12 # 开始上下左右搜索 13 for i in range(4): 14 a, b = x+dx[i], y+dy[i] 15 if 0<= a < n and 0<= b < m and sig[a][b] == 2: 16 if find(n, m, sig, begin, end, a, b): 17 return True 18 # 走到这,说明走不通(还原) 19 sig[x][y] += 1 20 return False 21 22 if __name__ == '__main__': 23 nms, sigs, begins, ends = [], [], [], [] 24 maps = {".": 2, "X": 1} 25 # 输入 26 t = int(sys.stdin.readline().strip("\n")) # t组测试 27 for i in range(t): 28 n, m = map(int, sys.stdin.readline().split(" ")) 29 nms.append([n, m]) 30 sig = [] 31 for _ in range(n): 32 line = sys.stdin.readline().strip("\n") 33 sig.append(list(map(lambda i:maps[i], line))) # 映射转换 34 sigs.append(sig) 35 begins.append(list(map(int, sys.stdin.readline().split(" ")))) 36 ends.append(list(map(int, sys.stdin.readline().split(" ")))) 37 # 测试 38 for i in range(t): 39 n, m = nms[i] 40 sig = sigs[i] 41 # print("sig = \n{}".format(np.array(sig))) 42 begin, end = begins[i], ends[i] 43 if find(n, m, sig, begin, end, begin[0]-1, begin[1]-1): 44 print("YES") 45 else: 46 print("NO")
3. 冰激凌配料
输入:
3 10
2 5 3
2 1 3输出:
4
说明:
# 4 (7)
# 5 (12)
# 6 (18)
# 7 (24)
分析:
- 这题对时间复杂度有要求,如果只是单纯的暴力求解的话,只能过20%
- 需要精简中间计算和遍历环节
- 则,将 w 和 v 按照数量 w 进行排序,从小到大开始累加
1 def maxGet(money, goods, prices): 2 get = min(goods) # 现在储存能成产的量 3 goods = list(map(lambda x:x-get, goods)) # 更新库存 4 # 将goods, prices 按照库存剩余量排序 5 goods, prices = zip(*sorted(zip(goods, prices))) 6 goods, prices = list(goods), list(prices) 7 goods.append(float("inf")) # 添加哨兵 8 index = cost = 0 9 while True: 10 # 补齐index和index+1之间的差距 11 gap = goods[index+1] - goods[index] 12 cost += prices[index] 13 if gap * cost < money: 14 money -= gap * cost 15 get += gap 16 index += 1 17 else: 18 get += money // cost 19 break 20 return get 21 22 import sys 23 if __name__ == '__main__': 24 n, m = map(int, sys.stdin.readline().split(" ")) 25 w = list(map(int, sys.stdin.readline().split(" "))) 26 v = list(map(int, sys.stdin.readline().split(" "))) 27 print(maxGet(m, w, v))
4. 飞机航线
输入:
3 5 3
1 2 7
2 3 6
1 3 9
2 1 2
3 1 1
1 2 3 8
2 3 3 1
2 1 3 5
输出:
8
8
9
分析:
我个人理解是:
- 建立一个n*n的关系矩阵arr,arr[i][j] 表示飞机从城市i直接飞往城市 j 的机票价格(即,带权值矩阵---图)
- 求解从城市1到城市n之间的最小距离
- 最小路径问题的求解方法,一般有:迪杰斯特拉算法、佛洛依德算法、广度优先遍历。
- (目前代码还没有完全调试正确,后续补上代码环节)
5. 探险
输入:
6
1 2 3
8 9 10
5 0 5
-9 -8 -10
0 1 2
5 4 6输出:
27说明:
小Q走 3-> 10 -> 0 -> -9 -> 0 -> 5 这条路径得到最高的分数,其中 -9 将取相反数,得 9 分
分析:
- 遇见0,取相反数,这道题的最终目标是取最大,所以需要同时记录opt_min和opt_max
- opt_max[ i ][ j ]:表示走到该位置最大的分数
- opt_min[ i ][ j ]:表示走到该位置最小的分数
1 import sys 2 import numpy as np 3 import copy 4 5 def maxScore(n, scores): 6 # opt_max[i][j]:表示走到该位置最大的分数 7 # opt_min[i][j]:表示走到该位置最小的分数 8 opt_max = [[0 for _ in range(3)] for _ in range(n)] 9 opt_max[0][:] = scores[0][:] # 初始化起始位置 10 opt_min = copy.deepcopy(opt_max) # 深层拷贝 11 for i in range(1, n): 12 # j = 0 13 if scores[i][0] == 0: 14 opt_max[i][0] = -min(opt_min[i-1][0], opt_min[i-1][1]) 15 opt_min[i][0] = -max(opt_max[i-1][0], opt_max[i-1][1]) 16 else: 17 opt_max[i][0] = max(opt_max[i-1][0], opt_max[i-1][1]) + \ 18 scores[i][0] 19 opt_min[i][0] = min(opt_min[i-1][0], opt_min[i-1][1]) + \ 20 scores[i][0] 21 # j = 1 22 if scores[i][1] == 0: 23 opt_max[i][1] = -min(opt_min[i-1][0], opt_min[i-1][1], \ 24 opt_min[i-1][2]) 25 opt_min[i][1] = -max(opt_max[i-1][0], opt_max[i-1][1], \ 26 opt_max[i-1][2]) 27 else: 28 opt_max[i][1] = max(opt_max[i-1][0], opt_max[i-1][1], \ 29 opt_max[i-1][2]) + scores[i][1] 30 opt_min[i][1] = min(opt_min[i-1][0], opt_min[i-1][1], \ 31 opt_min[i-1][2]) + scores[i][1] 32 # j = 2 33 if scores[i][2] == 0: 34 opt_max[i][2] = -min(opt_min[i-1][1], opt_min[i-1][2]) 35 opt_min[i][2] = -max(opt_max[i-1][1], opt_max[i-1][2]) 36 else: 37 opt_max[i][2] = max(opt_max[i-1][1], opt_max[i-1][2]) + \ 38 scores[i][2] 39 opt_min[i][2] = min(opt_min[i-1][1], opt_min[i-1][2]) + \ 40 scores[i][2] 41 # print(np.array(opt_max)) 42 # print(np.array(opt_min)) 43 return max(opt_max[-1]) 44 45 46 if __name__ == '__main__': 47 n = int(sys.stdin.readline().strip("\n")) 48 scores = [] 49 for i in range(n): 50 scores.append(list(map(int, sys.stdin.readline().split(" ")))) 51 print(maxScore(n, scores))