#include <bits/stdc++.h>
using namespace std;
int dp[1 << 6][1 << 6], ndp[1 << 6][1 << 6], SZ;
int n, m;
void clear(bool second = false) {
  if (second)
    for (int i = 0; i < SZ; ++i)
      for (int j = 0; j < SZ; ++j) ndp[i][j] = 1000000;
  else
    for (int i = 0; i < SZ; ++i)
      for (int j = 0; j < SZ; ++j) dp[i][j] = 1000000;
}
int go[1 << 6][1 << 6];
int GO(int pmsk, int msk) {
  int ret = 0;
  for (int i = 0; i < n; ++i) {
    bool OK = false;
    if ((msk & (1 << i)) || (pmsk & (1 << i))) OK = true;
    if (i > 0 && (msk & (1 << (i - 1)))) OK = true;
    if (i + 1 < n && (msk & (1 << (i + 1)))) OK = true;
    if (!OK) ret |= (1 << i);
  }
  return ret;
}
inline bool fit(int msk, int inside) { return !((msk & inside) ^ msk); }
int main() {
  cin >> n >> m;
  if (n > m) swap(n, m);
  SZ = (1 << n);
  clear();
  for (int i = 0; i < SZ; ++i) dp[0][i] = __builtin_popcount(i);
  for (int pmsk = 0; pmsk < SZ; ++pmsk)
    for (int msk = 0; msk < SZ; ++msk) go[pmsk][msk] = GO(pmsk, msk);
  for (int S = 1; S < m; ++S) {
    clear(true);
    for (int pmsk = 0; pmsk < SZ; ++pmsk)
      for (int msk = 0; msk < SZ; ++msk) {
        for (int next = 0; next < SZ; ++next)
          if (fit(go[pmsk][msk], next))
            ndp[msk][next] =
                min(ndp[msk][next], __builtin_popcount(next) + dp[pmsk][msk]);
      }
    memcpy(dp, ndp, sizeof ndp);
  }
  int ans = 1000000;
  for (int pmsk = 0; pmsk < SZ; ++pmsk)
    for (int msk = 0; msk < SZ; ++msk)
      if (go[pmsk][msk] == 0) ans = min(ans, dp[pmsk][msk]);
  cout << n * m - ans << '\n';
  return 0;
}
