#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#pragma GCC optimize("Ofast")
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#pragma GCC optimize(5)
#pragma GCC optimize(6)
#pragma GCC optimize(7)
#pragma GCC optimize(8)
#pragma GCC optimize(9)
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
const int dx[5] = {0, 1, -1, 0, 0};
const int dy[5] = {0, 0, 0, 1, -1};
int n, m, best;
long long g[45], rest[45];
void dfs(long long mask, int cur, int cura) {
  if (cura >= best) return;
  if (cur >= n * m) return;
  if (mask == (1LL << n * m) - 1)
    best = cura;
  else if ((mask | rest[cur]) ^ (1LL << n * m) - 1)
    return;
  else
    dfs(mask | g[cur], cur + 1, cura + 1), dfs(mask, cur + 1, cura);
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      int num = i * m + j;
      for (int k = 0; k < 5; ++k) {
        int x = i + dx[k], y = j + dy[k];
        if (x < 0 || x >= n || y < 0 || y >= m) continue;
        g[num] |= 1LL << x * m + y;
      }
    }
  for (int i = n * m - 1; i >= 0; --i) rest[i] = rest[i + 1] | g[i];
  best = n * m;
  dfs(0, 0, 0);
  printf("%d\n", n * m - best);
  return 0;
}
