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))