p167.ans1
======================
Oil : 100
1 1
1 2
1 3
2 1

=================
p167.cpp
======================
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

const int inf = (int)1e9 + 42;

int n, m, k;
vector<vector<int>> a;

void read() {
    cin >> n >> m >> k;
    a.resize(n, vector<int>(m));
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            cin >> a[i][j];
        }
    }
}

vector<vector<int>> psum;

int get_sum(int x1, int y1, int x2, int y2) {
    int res = psum[x2][y2];
    if(x1 > 0) {
        res -= psum[x1 - 1][y2];
    }
    if(y1 > 0) {
        res -= psum[x2][y1 - 1];
    }
    if(x1 > 0 && y1 > 0) {
        res += psum[x1 - 1][y1 - 1];
    }
    return res;
}

vector<vector<vector<vector<vector<int>>>>> dp;

int rec(int row, int l, int r, int cnt, int state) {
    if(row == n) {
        return (cnt == 0) ? 0 : -inf;
    }
    if(cnt == 0) {
        return 0;
    }

    int& memo = dp[row][l][r][cnt][state];
    if(memo != -1) {
        return memo;
    }

    bool can_move_l = (state & 1) == 0;
    bool can_move_r = (state & 2) == 0;

    memo = -inf;

    for(int new_l = 0; new_l <= m; new_l++) {
        for(int new_r = new_l; new_r < m; new_r++) {
            int overlap = min(r, new_r) - max(l, new_l) + 1;
            int new_cnt = cnt - (new_r - new_l + 1);
            if(new_cnt < 0) {
                continue;
            }

            if(overlap <= 0) {
                continue;
            }

            if(!can_move_l && new_l < l) {
                continue;
            }

            if(!can_move_r && new_r > r) {
                continue;
            }

            bool we_shrunk_left = new_l > l;
            bool we_shrunk_right = new_r < r;
            int new_state =
                state | (we_shrunk_left ? 1 : 0) | (we_shrunk_right ? 2 : 0);
            int sum = get_sum(row, new_l, row, new_r);
            memo =
                max(memo, sum + rec(row + 1, new_l, new_r, new_cnt, new_state));
        }
    }

    return memo;
}

void solve() {
    // A "convex" (row-monotone) region: each occupied row is a contiguous
    // segment [l, r], the left boundary first stays/moves right then the right
    // boundary stays/moves left, so the shape is monotone (no re-widening once
    // a side has shrunk). We DP over rows. The state is (row, l, r, cnt, mask)
    // where cnt is the remaining number of cells to place and the 2-bit mask
    // records whether the left/right boundary has already started shrinking
    // (once it has, that side may no longer expand). psum is a 2D prefix sum
    // for O(1) row-segment sums. rec returns the best oil achievable from the
    // given state; we try every starting row/segment, take the max, then
    // replay the same transitions matching the stored optimum to reconstruct
    // the chosen cells, finally printing them sorted.

    if(k == 0) {
        cout << "Oil : 0\n";
        return;
    }

    psum.assign(n, vector<int>(m, 0));
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            psum[i][j] = a[i][j];
            if(i > 0) {
                psum[i][j] += psum[i - 1][j];
            }
            if(j > 0) {
                psum[i][j] += psum[i][j - 1];
            }
            if(i > 0 && j > 0) {
                psum[i][j] -= psum[i - 1][j - 1];
            }
        }
    }

    dp.assign(
        n, vector<vector<vector<vector<int>>>>(
               m, vector<vector<vector<int>>>(
                      m, vector<vector<int>>(k + 1, vector<int>(4, -1))
                  )
           )
    );

    int ans = -inf;
    int start_row = -1, start_l = -1, start_r = -1;
    for(int row = 0; row < n; row++) {
        for(int l = 0; l < m; l++) {
            for(int r = l; r < m; r++) {
                int cnt = k - (r - l + 1);
                if(cnt >= 0) {
                    int sum = get_sum(row, l, row, r);
                    int res = sum + rec(row + 1, l, r, cnt, 0);
                    if(res > ans) {
                        ans = res;
                        start_l = l;
                        start_r = r;
                        start_row = row;
                    }
                }
            }
        }
    }

    cout << "Oil : " << ans << '\n';

    vector<pair<int, int>> cells;
    for(int i = start_l; i <= start_r; i++) {
        cells.emplace_back(start_row, i);
    }

    k -= (start_r - start_l + 1);
    ans -= get_sum(start_row, start_l, start_row, start_r);
    int state = 0;
    start_row++;
    while(k > 0) {
        int best_next_l = -1, best_next_r = -1, best_next_state = -1;
        bool can_move_l = (state & 1) == 0;
        bool can_move_r = (state & 2) == 0;
        for(int new_l = 0; new_l < m; new_l++) {
            for(int new_r = new_l; new_r < m; new_r++) {
                int overlap = min(start_r, new_r) - max(start_l, new_l) + 1;
                int new_cnt = k - (new_r - new_l + 1);
                if(new_cnt < 0) {
                    continue;
                }
                if(overlap <= 0) {
                    continue;
                }

                if(!can_move_l && new_l < start_l) {
                    continue;
                }

                if(!can_move_r && new_r > start_r) {
                    continue;
                }

                bool we_shrunk_left = new_l > start_l;
                bool we_shrunk_right = new_r < start_r;
                int new_state = state | (we_shrunk_left ? 1 : 0) |
                                (we_shrunk_right ? 2 : 0);
                int sum = get_sum(start_row, new_l, start_row, new_r);
                int next_res =
                    sum + rec(start_row + 1, new_l, new_r, new_cnt, new_state);
                if(next_res == ans) {
                    best_next_l = new_l;
                    best_next_r = new_r;
                    best_next_state = new_state;
                }
            }
        }

        assert(best_next_l != -1 && best_next_r != -1 && best_next_state != -1);

        for(int i = best_next_l; i <= best_next_r; i++) {
            cells.emplace_back(start_row, i);
        }

        ans -= get_sum(start_row, best_next_l, start_row, best_next_r);
        k -= (best_next_r - best_next_l + 1);
        start_row++;
        start_l = best_next_l;
        start_r = best_next_r;
        state = best_next_state;
    }

    sort(cells.begin(), cells.end());
    for(int i = 0; i < (int)cells.size(); i++) {
        cout << cells[i].first + 1 << ' ' << cells[i].second + 1 << '\n';
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}

=================
p167.in1
======================
2 3 4
10 20 30
40 2 3

=================
statement.txt
======================
167. I-country.
time limit per test: 0.75 sec.
memory limit per test: 65536 KB
input: standard
output: standard



According to top-secret A-country plans, I-country is divided into N*M equal squares, each square contains some oil resources. They want to occupy all the territory of I-country, but the UN (United Nations) will allow them to occupy only K squares. Of course, A-country want to get control over as many oil as possible, but, they will have to guard all their territory. So, they need their territory to be easy-controlled, i.e. from any square to any it must be possible to get moving only along two directions (selected from the next list: left, right, up, down; for different squares pairs of directions may differ).
You are to write a program, which determinies, what squares will be occupyed by A-country. If there are several solutions, you may output any.

Input
On the first line of input there are 3 integer numbers N,M,K (1<=N,M<=15, 0<=K<=N*M). Next N lines contains M integers each, which are the number of oil resource on that square. Each of this numbers lies in range of 0 to 1000.

Output
On the first line of output, write string "Oil : X", where integer number X --- the maximal number of oil which can be controlled by A-country. Next you should output K pairs of numbers --- coordinates of the squares which will be occupied by A-country. The first coordinate is number of row (top to bottom, starting from 1), second is number of column (left to right, starting from 1).

Sample test(s)

Input
2 3 4
10 20 30
40 2 3

Output
Oil : 100
1 1
1 2
1 3
2 1
Author:	NNSU #2 team
Resource:	
Date:	








=================
