#include #include #include #include #include using namespace std; using ll = long long; int N, M; ll X, C; vector> A; // 判定関数: 満足度の最小値を K 以上にできるか? bool check(ll K) { // dp[i][j][k]: // 位置 i にカテゴリ j (0..M-1) // 位置 i-1 にカテゴリ k (0..M-1) // とした時の、位置 0..i-1 までのペナルティ回数の最大値 vector>> dp(N, vector>(M, vector(M, -1))); // --- ベースケース: i = 1 (位置 0 と 1) --- for (int j = 0; j < M; ++j) { // cat[1] for (int k = 0; k < M; ++k) { // cat[0] // 位置 0 のペナルティを確定 int pen0 = (k == j) ? 1 : 0; ll B0 = A[0][k] - (ll)pen0 * C; if (B0 >= K) { dp[1][j][k] = pen0; } } } // --- DPループ: i = 2 から N-1 まで --- for (int i = 2; i < N; ++i) { for (int j = 0; j < M; ++j) { // cat[i] for (int k = 0; k < M; ++k) { // cat[i-1] for (int prev_k = 0; prev_k < M; ++prev_k) { // cat[i-2] int p_prev = dp[i - 1][k][prev_k]; if (p_prev == -1) continue; // 不可能な状態 // 位置 i-1 のペナルティを確定 int pen_i_minus_1 = ((k == prev_k) || (k == j)) ? 1 : 0; ll B_i_minus_1 = A[i - 1][k] - (ll)pen_i_minus_1 * C; if (B_i_minus_1 < K) continue; // K未満は不可 int p_current = p_prev + pen_i_minus_1; dp[i][j][k] = max(dp[i][j][k], p_current); } } } } // --- 最終判定: i = N-1 (最後の位置) --- for (int j = 0; j < M; ++j) { // cat[N-1] for (int k = 0; k < M; ++k) { // cat[N-2] int p_prev = dp[N - 1][j][k]; if (p_prev == -1) continue; // 位置 N-1 のペナルティを確定 int pen_N_minus_1 = (j == k) ? 1 : 0; ll B_N_minus_1 = A[N - 1][j] - (ll)pen_N_minus_1 * C; if (B_N_minus_1 < K) continue; int total_penalties = p_prev + pen_N_minus_1; if (total_penalties >= X) { return true; // K以上、X回以上を達成可能 } } } return false; // すべての配置で達成不可 } int main() { // 高速化 cin.tie(nullptr); ios::sync_with_stdio(false); cin >> N >> M >> X >> C; A.resize(N, vector(M)); for (int i = 0; i < N; ++i) { for (int j = 0; j < M; ++j) { cin >> A[i][j]; } } // 答え K の範囲で二分探索 ll low = 0; ll high = 1e9 + 7; // A[i][j]の最大値より少し大きければOK ll ans = 0; while (low <= high) { ll mid = low + (high - low) / 2; if (check(mid)) { // mid が達成可能なら、答えは mid かもしれない // (より大きい値を探す) ans = mid; low = mid + 1; } else { // mid が達成不可能なら、mid より小さい値を探す high = mid - 1; } } cout << ans << endl; return 0; }