## https://yukicoder.me/problems/no/3368 from collections import deque MAX_INT = 10 ** 18 MIN_INT = - 10 ** 18 def solve(N, M, C, X, A, min_value): rest = N - X enables = [] for i in range(N): row = [] for j in range(M): if A[i][j] >= min_value: row.append(j) enables.append(row) # keyは state , j * 2 + [すでに隣接するアイテムがあるかないかフラグ] row = enables[0] dp = {j * 2 :1 for j in row} best_3 = [MAX_INT] * (3 * 2) for state, x_value in dp.items(): for k in range(3): if best_3[2 * k] > x_value: for k_ in reversed(range(k, 2)): for l in range(2): best_3[2 * (k_ + 1) + l] = best_3[2 * k_ + l] best_3[2 * k] = x_value best_3[2 * k + 1] = state break for i in range(1, N): new_dp = {} for j in enables[i]: for k in range(3): x_value = best_3[2 * k] state = best_3[2 * k + 1] prev_j = state // 2 has_same_near = state % 2 if best_3[2 * k + 1] == MIN_INT: break if prev_j != j: new_x_value = x_value + 1 new_state = 2 * j else: if has_same_near == 1 and A[i][j] - C >= min_value: new_x_value = x_value new_state = 2 * j + 1 elif has_same_near == 0 and A[i][j] - C >= min_value and A[i - 1][prev_j] - C >= min_value: new_x_value = x_value - 1 new_state = 2 * j + 1 else: continue if new_state not in new_dp: new_dp[new_state] = MAX_INT new_dp[new_state] = min(new_dp[new_state], new_x_value) dp = new_dp best_3 = [MAX_INT] * (3 * 2) for state, x_value in dp.items(): for k in range(3): if best_3[2 * k] > x_value: for k_ in reversed(range(k, 2)): for l in range(2): best_3[2 * (k_ + 1) + l] = best_3[2 * k_ + l] best_3[2 * k] = x_value best_3[2 * k + 1] = state break for value in dp.values(): if 0 <= value <= rest: return True return False def main(): N, M, C, X = map(int, input().split()) A= [] for _ in range(N): A.append(list(map(int, input().split()))) max_a = -float("inf") min_a = float("inf") for row in A: max_a = max(max_a, max(row)) min_a = min(min_a, min(row) - C) low = min_a high = max_a while high - low > 1: mid = (high + low) // 2 if solve(N, M, C, X, A, mid): low = mid else: high = mid if solve(N, M, C, X, A, high): print(high) else: print(low) if __name__ == '__main__': main()