#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
template <class c>
struct rge {
  c b, e;
};
template <class c>
rge<c> range(c i, c j) {
  return rge<c>{i, j};
}
template <class c>
auto dud(c* x) -> decltype(cerr << *x, 0);
template <class c>
char dud(...);
struct debug {
  template <class c>
  debug& operator<<(const c&) {
    return *this;
  }
};
using ll = long long;
using ld = long double;
constexpr int nax = 1000 * 1000 + 105;
constexpr int infty = 1000 * 1000 * 1000 + 5;
constexpr int mod = 1000 * 1000 * 1000 + 7;
template <typename T>
void Splec(vector<T>& v, bool tyl) {
  const int n = (int)v.size();
  vector<T> nowy;
  if (n == 4) {
    nowy.push_back(v[1]);
    nowy.push_back(v[3]);
    nowy.push_back(v[0]);
    nowy.push_back(v[2]);
    swap(v, nowy);
    return;
  }
  for (int r = 0; r < 2; r++) {
    for (int i = r; i < n; i += 2) {
      nowy.push_back(v[i]);
    }
    if (tyl) reverse(nowy.begin(), nowy.end());
  }
  swap(v, nowy);
}
template <typename T>
void Popraw(vector<vector<int>>& tab, int n, int m, T obok) {
  for (int pow = 0; pow < 200 * 1000 / (n * m); pow++) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        if ((i and obok(tab[i][j], tab[i - 1][j])) or
            (j and obok(tab[i][j], tab[i][j - 1]))) {
          const int I = rand() % n;
          const int J = rand() % m;
          swap(tab[i][j], tab[I][J]);
        }
      }
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  auto obok2 = [n, m](int a, int b) -> bool {
    if (a / m == b / m) {
      return abs(a % m - b % m) <= 1;
    }
    return abs(a / m - b / m) <= 1 and a % m == b % m;
  };
  auto obok = [obok2](int a, int b) -> bool {
    a--;
    b--;
    const bool res = obok2(a, b);
    if (res) {
      debug() << "obok(" << a << ", " << b << ")";
    }
    return res;
  };
  vector<int> kol;
  if (n <= m) {
    for (int i = 1; i <= n * m; i++) kol.push_back(i);
  } else {
    for (int i = 1; i <= m; i++) {
      for (int j = 0; j < n; j++) kol.push_back(i + j * m);
    }
  }
  vector<vector<int>> tab;
  tab.resize(n);
  for (int i = 0; i < n; i++) tab[i].resize(m, -1);
  for (int proba = 0; proba < 6; proba++) {
    try {
      int nast = 1;
      if (proba < 2) {
        for (int i = 0; i < n; i++) {
          for (int j = 0; j < m; j++) {
            if ((i + j + proba) % 2 == 0) {
              tab[i][j] = kol[nast++ - 1];
            }
          }
        }
        for (int i = n - 1; i >= 0; i--) {
          for (int j = m - 1; j >= 0; j--) {
            if ((i + j + proba) % 2 == 1) {
              tab[i][j] = kol[nast++ - 1];
            }
          }
        }
      } else if (proba < 4) {
        for (int j = 0; j < m; j++) {
          for (int i = 0; i < n; i++) {
            if ((i + j + proba) % 2 == 0) {
              tab[i][j] = kol[nast++ - 1];
            }
          }
        }
        for (int j = 0; j < m; j++) {
          for (int i = 0; i < n; i++) {
            if ((i + j + proba) % 2 == 1) {
              tab[i][j] = kol[nast++ - 1];
            }
          }
        }
      } else {
        for (int i = 0; i < n; i++) {
          for (int j = 0; j < m; j++) {
            tab[i][j] = nast++;
          }
        }
        Splec(tab, proba == 6);
        for (int i = 0; i < n; i++) {
          Splec(tab[i], proba == 6);
        }
      }
      assert(nast == n * m + 1);
      Popraw(tab, n, m, obok);
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
          if (i and obok(tab[i][j], tab[i - 1][j])) throw 1;
          if (j and obok(tab[i][j], tab[i][j - 1])) throw 1;
        }
      }
      cout << "YES" << endl;
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
          cout << tab[i][j] << " ";
        }
        cout << "\n";
      }
      return 0;
    } catch (int x) {
    }
  }
  cout << "NO" << endl;
  return 0;
}
