#include using namespace std; const int N = 1007; int a[N][N]; int n, m, maxl; mt19937 mt(7); struct point{ int x, y; point(){} point(int x, int y){ this->x = x; this->y = y; } }; long long lis(const vector &v){ vector t; for(point p: v){ int l = 0, r = (int)t.size(); while(l != r){ int mid = (l + r) >> 1; if(a[p.x][p.y] <= t[mid]){ r = mid; } else{ l = mid + 1; } } if(l == (int)t.size()){ t.push_back(a[p.x][p.y]); } else{ t[l] = a[p.x][p.y]; } } return (long long)t.size(); } struct path{ vector v; long long score; bitset used[N]; path(int x, int y){ score = 0; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ used[i][j] = false; } } if(a[x][y] == -1){ return; } v.push_back(point(x, y)); while((int)v.size() < maxl){ vector adj, poss; used[x][y] = true; adj.push_back(point(x - 1, y)); adj.push_back(point(x + 1, y)); adj.push_back(point(x, y - 1)); adj.push_back(point(x, y + 1)); for(point p: adj){ if(p.x >= 1 && p.x <= n && p.y >= 1 && p.y <= m && a[p.x][p.y] != -1 && !used[p.x][p.y]){ poss.push_back(p); } } if(poss.empty()){ break; } int rnd = mt() % (int)poss.size(); bool ok = false; if(v.size() >= 2){ int idx = (int)v.size() - 1; if(a[v[idx].x][v[idx].y] > a[v[idx - 1].x][v[idx - 1].y] && a[poss[rnd].x][poss[rnd].y] < a[v[idx].x][v[idx].y]){ ok = true; } if(a[v[idx].x][v[idx].y] <= a[v[idx - 1].x][v[idx - 1].y] && a[poss[rnd].x][poss[rnd].y] >= a[v[idx].x][v[idx].y]){ ok = true; } } if(!ok){ rnd = mt() % (int)poss.size(); } v.push_back(poss[rnd]); x = poss[rnd].x; y = poss[rnd].y; } calc_score(); } path(const path &parent){ score = 0; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ used[i][j] = false; } } int rnd = mt() % (int)parent.v.size() + 1; for(int i = 0; i < rnd; i++){ v.push_back(parent.v[i]); used[parent.v[i].x][parent.v[i].y] = true; } int x = v.back().x; int y = v.back().y; if(a[x][y] == -1){ return; } //v.push_back(point(x, y)); while((int)v.size() < maxl){ vector adj, poss; used[x][y] = true; adj.push_back(point(x - 1, y)); adj.push_back(point(x + 1, y)); adj.push_back(point(x, y - 1)); adj.push_back(point(x, y + 1)); for(point p: adj){ if(p.x >= 1 && p.x <= n && p.y >= 1 && p.y <= m && a[p.x][p.y] != -1 && !used[p.x][p.y]){ poss.push_back(p); } } if(poss.empty()){ break; } int rnd = mt() % (int)poss.size(); v.push_back(poss[rnd]); x = poss[rnd].x; y = poss[rnd].y; } calc_score(); } path(const path &parent, bool b){ score = 0; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ used[i][j] = false; } } int rnd = mt() % (int)parent.v.size() + 1; for(int i = 0; i < rnd; i++){ v.push_back(parent.v[i]); used[parent.v[i].x][parent.v[i].y] = true; } reverse(v.begin(), v.end()); int x = v.back().x; int y = v.back().y; if(a[x][y] == -1){ return; } //v.push_back(point(x, y)); while((int)v.size() < maxl){ vector adj, poss; used[x][y] = true; adj.push_back(point(x - 1, y)); adj.push_back(point(x + 1, y)); adj.push_back(point(x, y - 1)); adj.push_back(point(x, y + 1)); for(point p: adj){ if(p.x >= 1 && p.x <= n && p.y >= 1 && p.y <= m && a[p.x][p.y] != -1 && !used[p.x][p.y]){ poss.push_back(p); } } if(poss.empty()){ break; } int rnd = mt() % (int)poss.size(); v.push_back(poss[rnd]); x = poss[rnd].x; y = poss[rnd].y; } calc_score(); } void calc_score(){ score = (long long)lis(v); reverse(v.begin(), v.end()); score *= (long long )lis(v); reverse(v.begin(), v.end()); } }; clock_t timer; bool time_left(){ return (float)(clock() - timer) / (float)CLOCKS_PER_SEC <= (float)4.5; } int main(){ timer = clock(); ios::sync_with_stdio(false); cin.tie(NULL); freopen("path.in", "r", stdin); freopen("path.out", "w", stdout); cin >> n >> m; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ cin >> a[i][j]; } } cin >> maxl; path best(1, 1); while(time_left()){ path curr(mt() % n + 1, mt() % m + 1); if(curr.score > best.score){ best = curr; } curr = path(best); if(curr.score > best.score){ best = curr; } curr = path(best, true); if(curr.score > best.score){ best = curr; } } cout << best.v.size() << "\n"; for(point p: best.v){ cout << p.x << " " << p.y << "\n"; } return 0; }