#include <bits/stdc++.h>
using namespace std;
using namespace std;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const double pi = acos(-1.0);
int ans = -1;
int R[2000 * 2000], L[2000 * 2000], U[2000 * 2000], D[2000 * 2000];
int col[2000 * 2000];
int S[2000];
struct DancingLinks {
  int sz;
  int first, nowrow;
  void remove(int &c) {
    for (int i = D[c]; i != c; i = D[i]) {
      L[R[i]] = L[i];
      R[L[i]] = R[i];
    }
  }
  void resume(int &c) {
    for (int i = U[c]; i != c; i = U[i]) {
      L[R[i]] = i;
      R[L[i]] = i;
    }
  }
  int h() {
    bool hash[2000] = {};
    int ret = 0;
    for (int c = R[0]; c != 0; c = R[c]) {
      if (hash[c]) continue;
      ret++;
      hash[c] = true;
      for (int i = D[c]; i != c; i = D[i]) {
        for (int j = R[i]; j != i; j = R[j]) {
          hash[col[j]] = true;
        }
      }
    }
    return ret;
  }
  bool dfs(int deep, int lim) {
    if (deep + h() > lim) return false;
    if (R[0] == 0) return true;
    int idx = R[0];
    for (int i = R[idx]; i != 0; i = R[i]) {
      if (S[i] < S[idx]) idx = i;
    }
    for (int i = D[idx]; i != idx; i = D[i]) {
      remove(i);
      for (int j = R[i]; j != i; j = R[j]) remove(j);
      if (dfs(deep + 1, lim)) {
        for (int j = L[i]; j != i; j = L[j]) resume(j);
        resume(i);
        return true;
      }
      for (int j = L[i]; j != i; j = L[j]) resume(j);
      resume(i);
    }
    return false;
  }
  void Insert(int i, int j) {
    if (nowrow != i) {
      L[first] = sz - 1;
      R[sz - 1] = first;
      first = sz;
      nowrow = i;
    }
    L[sz] = sz - 1;
    R[sz] = sz + 1;
    D[sz] = j;
    D[U[j]] = sz;
    U[sz] = U[j];
    U[j] = sz;
    col[sz] = j;
    S[j]++;
    sz++;
  }
  void init(int n) {
    nowrow = 0;
    first = 0;
    sz = 0;
    for (int i = 0; i <= n; i++) {
      U[i] = i;
      D[i] = i;
      L[i] = i - 1;
      R[i] = i + 1;
    }
    L[0] = n;
    R[n] = 0;
    sz = n + 1;
    memset(S, 0, sizeof(S[0]) * (n + 1));
  }
  int solve(int lo, int hi) {
    int mid;
    L[first] = sz - 1;
    R[sz - 1] = first;
    while (lo <= hi) {
      mid = (lo + hi) >> 1;
      if (dfs(0, mid))
        ans = mid, hi = mid - 1;
      else
        lo = mid + 1;
    }
    return ans;
  }
} dlx;
int n, m;
int getc(int x, int y) { return (x - 1) * m + y; }
int DL[2000][2000];
int main() {
  while (cin >> n >> m) {
    dlx.init(n * m);
    memset(DL, 0, sizeof(DL));
    int x, y;
    for (int i = 1; i <= n; ++i)
      for (int j = 1; j <= m; ++j) {
        int ii = getc(i, j);
        for (int k = 0; k < 4; ++k) {
          x = i + dx[k];
          y = j + dy[k];
          if (x >= 1 && x <= n && y >= 1 && y <= m) {
            DL[ii][getc(x, y)] = 1;
          }
        }
        DL[ii][ii] = 1;
      }
    for (int i = 1; i <= n * m; ++i)
      for (int j = 1; j <= n * m; ++j) {
        if (DL[i][j]) dlx.Insert(i, j);
      }
    cout << n * m - dlx.solve(0, n * m + 2) << endl;
  }
  return 0;
}
