import heapq def main(): import sys input = sys.stdin.read().split() idx = 0 N = int(input[idx]); idx +=1 M = int(input[idx]); idx +=1 K = int(input[idx]); idx +=1 T = int(input[idx]); idx +=1 magic = {} for _ in range(K): A = int(input[idx])-1; idx +=1 B = int(input[idx])-1; idx +=1 C = int(input[idx]); idx +=1 D = int(input[idx]); idx +=1 magic[(A,B)] = (C, D) # Directions: up, down, left, right dirs = [(-1,0), (1,0), (0,-1), (0,1)] # For each cell (i,j), keep a list of (time, fatigue) sorted by time state = [[[] for _ in range(M)] for _ in range(N)] heap = [] heapq.heappush(heap, (0, 0, 0, 0)) # (fatigue, time, i, j) state[0][0].append( (0, 0) ) found = False answer = -1 while heap: d, t, i, j = heapq.heappop(heap) if i == N-1 and j == M-1: if t <= T: answer = d found = True break else: continue # If this state is outdated, skip current_list = state[i][j] # Binary search to check if this state is valid left, right = 0, len(current_list) while left < right: mid = (left + right) // 2 if current_list[mid][0] <= t: left = mid +1 else: right = mid pos = left -1 if pos <0 or current_list[pos][1] < d: continue # Generate moves for di, dj in dirs: ni = i + di nj = j + dj if 0<=ni<N and 0<=nj<M: new_time = t +1 new_d = d # Check if this state can be added to ni, nj target_list = state[ni][nj] insert_pos = len(target_list) for idx_in_list in range(len(target_list)): ct, cd = target_list[idx_in_list] if ct <= new_time and cd <= new_d: insert_pos = -1 break if ct >= new_time: insert_pos = idx_in_list break if insert_pos == -1: continue # Now check from insert_pos backwards new_entries = [] added = False # Check previous entries if insert_pos >0: prev_t, prev_d = target_list[insert_pos-1] if prev_t <= new_time and prev_d <= new_d: continue # Remove all entries after insert_pos that have time >= new_time and d >= new_d start = insert_pos while start < len(target_list): ct, cd = target_list[start] if ct < new_time: start +=1 continue if cd >= new_d: break else: start +=1 # The entries from insert_pos to start-1 are to be removed # The new entry is (new_time, new_d) # So, target_list becomes target_list[:insert_pos] + [new_entry] + target_list[start:] new_entry = (new_time, new_d) new_target_list = target_list[:insert_pos] + [new_entry] + target_list[start:] state[ni][nj] = new_target_list heapq.heappush(heap, (new_d, new_time, ni, nj)) # Check if current cell is magic if (i,j) in magic: C, D_val = magic[(i,j)] new_time = t - C +1 new_d = d + D_val # Check if this state can be added to i,j target_list = state[i][j] insert_pos = len(target_list) for idx_in_list in range(len(target_list)): ct, cd = target_list[idx_in_list] if ct <= new_time and cd <= new_d: insert_pos = -1 break if ct >= new_time: insert_pos = idx_in_list break if insert_pos == -1: continue # Check previous entries added = False if insert_pos >0: prev_t, prev_d = target_list[insert_pos-1] if prev_t <= new_time and prev_d <= new_d: continue # Remove entries that are dominated start = insert_pos while start < len(target_list): ct, cd = target_list[start] if ct < new_time: start +=1 continue if cd >= new_d: break else: start +=1 new_entry = (new_time, new_d) new_target_list = target_list[:insert_pos] + [new_entry] + target_list[start:] state[i][j] = new_target_list heapq.heappush(heap, (new_d, new_time, i, j)) print(answer if found else -1) if __name__ == '__main__': main()