AtCoder Beginner Contest 317 題解 (A - E)
All problems solved by python
題意
給定 N N N 瓶藥水以及其可以恢復的生命值 P i P_i P i 、當前生命值 H H H 、目標生命值 X X X ,求哪瓶藥水可以使生命回復到目標生命值或以上,並且這瓶藥水的功效要最小。
思路
對所有藥水做遍歷,保存符合條件的藥水。
1 2 3 4 5 6 7 8 9 10 11 12 N, H, X = map (int , input ().split(" " )) P = list (map (int , input ().split(" " ))) ans = -1 for i, p in enumerate (P): if H + p == X: ans = i + 1 break elif H + p > X: if ans == -1 or p < P[ans]: ans = i + 1 print (ans)
題意
給定長度為 N N N 的數列 A A A ,其為長度為 N + 1 N+1 N + 1 的連續數列的子集合,找出缺少的那個數為何。
思路
排序後由小到大遍歷所有元素,若當前元素不等於前一個元素+1,則此處就是缺少的數。
1 2 3 4 5 6 7 8 N = int (input ()) A = list (map (int , input ().split(" " ))) A.sort() for i in range (1 , N): if A[i] - A[i-1 ] > 1 : print (A[i-1 ]+1 ) break
題意
給定 N N N 個點和 M M M 條邊,以及每條邊對應的權重 C i C_i C i ,求最長的路徑
限制
2 < = N < = 10 2 <= N <= 10 2 <= N <= 10
思路:DFS
構建出相鄰矩陣後,對每個點當作起點做DFS即可,並且令DFS返回路徑的長度,在以N個點作為起點的最大路徑中,再取其中的最大值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 N, M = map (int , input ().split(" " )) edges = [list (map (int , input ().split(" " ))) for _ in range (M)] if M == 1 : print (edges[0 ][2 ]) exit() adj = [[0 ]*(N+1 ) for _ in range (N+1 )] for edge in edges: X, Y, W = edge adj[X][Y] = W adj[Y][X] = W visited = [False for _ in range (N+1 )] ans = 0 def dfs (v ): cur = 0 visited[v] = True for j in range (1 , N+1 ): if adj[v][j] != 0 and not visited[j]: res = dfs(j) cur = max (cur, res+adj[v][j]) visited[v] = False return cur for i in range (1 , N+1 ): ans = max (ans, dfs(i)) print (ans)
題意
給定 N N N 個選區,以及每個選區中兩個候選人分別的得票數 X i X_i X i 、Y i Y_i Y i 、該選區的席次 Z i Z_i Z i ,求若X要贏得一半以上的席次,需要從對手手中搶走多少票。
限制
1 ≤ N ≤ 100 1 \leq N \leq 100 1 ≤ N ≤ 100
X i + Y i X_i+Y_i X i + Y i is odd.
∑ i = 1 N Z i ≤ 1 0 5 \sum_{i=1}^N Z_i \leq 10^5 ∑ i = 1 N Z i ≤ 1 0 5
∑ i = 1 N Z i \sum_{i=1}^N Z_i ∑ i = 1 N Z i is odd.
思路:DP
令 d p [ i ] dp[i] d p [ i ] 表示取得i個席位所需要的最少票數
令 x x x 、y y y 、z z z 表示每個選區的兩位候選人的分別得票數,以及席次,計算需要搶走的票數 v o t e vote v o t e
可寫出轉移方程為 d p [ i ] = m i n ( d p [ i ] , d p [ i − z ] + v o t e ) dp[i] = min(dp[i], dp[i-z] + vote) d p [ i ] = min ( d p [ i ] , d p [ i − z ] + v o t e )
在所有取得一半以上席位所需要的最少票數中,取最小值即為答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 N = int (input ()) MAX_ZSUM = 10 **5 dp = [0 ] + [float ("inf" )] * MAX_ZSUM ZSUM = 0 for _ in range (N): x,y,z = map (int ,input ().split()) ZSUM += z vote = max ((y-x+1 )//2 , 0 ) for i in range (MAX_ZSUM-1 , z-1 , -1 ): dp[i] = min (dp[i], dp[i-z] + vote) ans = min (dp[(ZSUM+1 )//2 :]) print (ans)
題意
給定一個迷宮 M a z e Maze M a ze ,其中有若干個監視者,其朝向分別用<>^v
表示,不能被監視者的視線看到,求能否從給定的起點走到終點,並且輸出路徑長度。
思路:用BFS走迷宮
首先先構建迷宮的矩陣,並在上下左右加上牆壁,以免出界
再來對迷宮矩陣做處理,確定哪些路徑可走
先找出起點、終點、以及所有監視者的位置
再來處理監視者,為了不影響對其他監視者的處理,依照題目所述,先標記為 ! ! !
最後將地圖中的可走路徑標記為0,牆壁或可視為牆壁的符號標記為-1。
從起點開始做BFS,並且對可走路徑更新從起點走到此位置的最小距離
若找到終點或所有可走路徑都走完就終止,因為起點不等於終點,所以可以用走到終點的路徑長度是否為0 0 0 來判斷能不能走到終點。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 H , W = map (int , input ().split(" " )) Maze = [list (f"#{input ()} #" ) for _ in range (H)] Maze = [["#" ]*(W+2 )] + Maze + [["#" ]*(W+2 )] start = goal = None arrows = [] for i in range (1 , H+1 ): for j in range (1 , W+1 ): if Maze[i][j] == "S" : start = (i, j) elif Maze[i][j] == "G" : goal = (i, j) elif Maze[i][j] in "<>^v" : arrows.append((i, j)) arrow_map = {"<" :(0 , -1 ), ">" :(0 , 1 ), "^" :(-1 , 0 ), "v" :(1 , 0 )} for pi, pj in arrows: di, dj = arrow_map[Maze[pi][pj]] i, j = pi+di, pj+dj while Maze[i][j] not in "#<>^v" : Maze[i][j] = "!" i, j = i+di, j+dj for i in range (H+2 ): for j in range (W+2 ): if Maze[i][j] in "#!<>^v" : Maze[i][j] = -1 else : Maze[i][j] = 0 from collections import dequequeue = deque([start]) while queue: pi, pj = queue.popleft() if (pi, pj) == goal: break for di, dj in [(-1 , 0 ), (1 , 0 ), (0 , -1 ), (0 , 1 )]: if Maze[pi+di][pj+dj] == 0 : Maze[pi+di][pj+dj] = Maze[pi][pj] + 1 queue.append((pi+di, pj+dj)) print (-1 ) if Maze[goal[0 ]][goal[1 ]] == 0 else print (Maze[goal[0 ]][goal[1 ]])