#include <bits/stdc++.h>
using namespace std;
template <typename T>
ostream &operator<<(ostream &o, vector<T> v) {
  if (v.size() > 0) o << v[0];
  for (unsigned i = 1; i < v.size(); i++) o << " " << v[i];
  return o << endl;
}
template <typename U, typename V>
ostream &operator<<(ostream &o, pair<U, V> p) {
  return o << "(" << p.first << ", " << p.second << ") ";
}
template <typename T>
istream &operator>>(istream &in, vector<T> &v) {
  for (unsigned i = 0; i < v.size(); i++) in >> v[i];
  return in;
}
struct UnionFind {
  vector<int> comp;
  vector<int> size;
  UnionFind(int n) : comp(n), size(n, 1) {
    for (int(i) = 0; (i) < (int)(n); ++(i)) comp[i] = i;
  }
  bool merge(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) return false;
    size[a] = size[b] = size[a] + size[b];
    comp[a] = b;
    return true;
  }
  int getSize(int a) { return size[find(a)]; }
  int find(int a) {
    while (comp[a] != a) a = comp[a] = comp[comp[a]];
    return a;
  }
};
void fillvals(vector<vector<int>> &a, pair<int, int> pos, int v, int nV) {
  int n = a.size();
  int m = a[0].size();
  vector<vector<bool>> sett(n, vector<bool>(m));
  int i, j;
  tie(i, j) = pos;
  assert(a[i][j] == v);
  vector<pair<int, int>> st;
  st.push_back(pos);
  int xx = 0;
  while (xx < nV) {
    assert(st.size());
    pair<int, int> npos = st.back();
    st.pop_back();
    tie(i, j) = npos;
    if (sett[i][j]) continue;
    sett[i][j] = 1;
    a[i][j] = v;
    if (i > 0 && a[i - 1][j] >= v && !sett[i - 1][j])
      st.push_back(make_pair((i - 1), (j)));
    if (i < n - 1 && a[i + 1][j] >= v && !sett[i + 1][j])
      st.push_back(make_pair((i + 1), (j)));
    if (j > 0 && a[i][j - 1] >= v && !sett[i][j - 1])
      st.push_back(make_pair((i), (j - 1)));
    if (j < m - 1 && a[i][j + 1] >= v && !sett[i][j + 1])
      st.push_back(make_pair((i), (j + 1)));
    xx++;
  }
  for (int(i) = 0; (i) < (int)(n); ++(i))
    for (int(j) = 0; (j) < (int)(m); ++(j)) {
      if (!sett[i][j]) a[i][j] = 0;
    }
}
int main() {
  ios_base::sync_with_stdio(false);
  int n, m;
  long long k;
  cin >> n >> m >> k;
  vector<pair<int, pair<int, int>>> stacks(n * m);
  vector<vector<int>> vals(n, vector<int>(m));
  int kk = 0;
  for (int(i) = 0; (i) < (int)(n); ++(i))
    for (int(j) = 0; (j) < (int)(m); ++(j)) {
      int a;
      cin >> a;
      stacks[kk++] = make_pair((a), (make_pair((i), (j))));
      vals[i][j] = a;
    }
  vector<vector<bool>> expl(n, vector<bool>(m));
  sort((stacks).begin(), (stacks).end(), greater<pair<int, pair<int, int>>>());
  map<int, pair<int, int>> sizes;
  UnionFind uf(n * m);
  for (int(x) = 0; (x) < (int)(n * m); ++(x)) {
    int i, j;
    tie(i, j) = stacks[x].second;
    int v = stacks[x].first;
    int kk = i * m + j;
    if (i > 0 && vals[i - 1][j] >= v) {
      uf.merge(kk, kk - m);
    }
    if (i < n - 1 && vals[i + 1][j] >= v) {
      uf.merge(kk, kk + m);
    }
    if (j > 0 && vals[i][j - 1] >= v) uf.merge(kk, kk - 1);
    if (j < m - 1 && vals[i][j + 1] >= v) uf.merge(kk, kk + 1);
    int sz = uf.getSize(kk);
    if (sz > sizes[v].first) sizes[v] = make_pair((sz), (x));
  }
  long long x = 1;
  int f = -1;
  while (x <= n * m) {
    if (k % x) {
      x++;
      continue;
    }
    long long h = k / x;
    if (h < 1000000007 && sizes.count(h) && sizes[h].first >= x) {
      f = sizes[h].second;
      break;
    }
    x++;
  }
  if (f < 0)
    cout << "NO\n";
  else {
    fillvals(vals, stacks[f].second, stacks[f].first, x);
    cout << "YES\n";
    for (int(i) = 0; (i) < (int)(n); ++(i)) cout << vals[i];
  }
}
