#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <numeric>
#include <cmath>
#include<algorithm>
using namespace std;

//ユーティリティ

#define INF 1e9
#define all(v) v.begin(), v.end()
#define rep(i,n) for(int i=0; i<n; i++)
#define vmax(v) *max_element(all(v))
#define vmin(v) *min_element(all(v))

//maxを更新しつつ、変わったか返す
template<class T>bool chmax(T &former, const T &b) {if (former<b) {former=b;return true;} return false;}
template<class T>bool chmin(T &former, const T &b) {if (former>b) {former=b;return true;} return false;}

//データ読み込み

template<class TypeInt> TypeInt input_type_int2(TypeInt &a, TypeInt &b) {
	cin >> a >> b;
	cin.ignore();	
}

void input_int2(int &a, int &b) {
	cin >> a >> b;
	cin.ignore();
}

void input_ll_int2(long long &a, long long &b) {
	cin >> a >> b;
	cin.ignore();
}

void input_int3(int &a, int &b, int &c) {
	cin >> a >> b >> c;	
	cin.ignore();
}

void input_int_array(int n,vector<int> &vec) {
	for (int i=0,tmp=0; i<n && cin >> tmp; i++) vec[i]=tmp;
}

void input_int_matrix(int n, int m, vector<vector<int>> &matrix) {
	int tmp;
	for(int i=0; i<n; i++) {
		for (int j=0; j<m; j++) {
			cin >> tmp;
			matrix[i][j] = tmp;
		}
	}
}

void input_int_var_array(int n,vector<int> &vec) {
	for (int tmp=0; cin >> tmp;) {
		vec.push_back(tmp);
	}
}

void input_int_var_matrix(int n, int m, vector<vector<int>> &matrix) {
	int tmp;
	for(int i=0; i<n; i++) {
		for (int j=0; j<m; j++) {
			cin >> tmp;
			matrix[i][j] = tmp;
		}
	}
}

void input_var_str(vector<string> & array) {
	string s;
	getline(cin, s);
	
	stringstream ss{s};
	while(getline(ss, s, ' ')) {
		array.push_back(s);
	}
}

void input_var_int(vector<int> &array) {
	string s;
	getline(cin, s);
	
	stringstream ss{s};
	while(getline(ss, s, ' ')) {
		array.push_back(stoi(s));
	}
}

void input_var_int(set<int> &array) {
	string s;
	getline(cin, s);
	
	stringstream ss{s};
	while(getline(ss, s, ' ')) {
		array.insert(stoi(s));
	}
}

//テスト用出力

template <typename T> void print_var_vector(vector<T> vec) {
	for(typename vector<T>::iterator i=begin(vec); i!=end(vec); i++) {
		cout << *i;
	}
	cout << endl;
}

void print_vector(int N, vector<int> vec) {
	for(int i=0; i<N; i++){
		cout << vec[i] << " ";
	}
	cout << endl;
}

//データ構造
template< typename Monoid >
struct SegmentTree {
  using F = function< Monoid(Monoid, Monoid) >;
 
  int sz;
  vector< Monoid > seg;
 
  const F f;
  const Monoid M1;
 
  SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while(sz < n) sz <<= 1;
    seg.assign(2 * sz, M1);
  }
 
  void set(int k, const Monoid &x) {
    seg[k + sz] = x;
  }
 
  void build() {
    for(int k = sz - 1; k > 0; k--) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }
 
  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while(k >>= 1) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }
 
  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) L = f(L, seg[a++]);
      if(b & 1) R = f(seg[--b], R);
    }
    return f(L, R);
  }
 
  Monoid operator[](const int &k) const {
    return seg[k + sz];
  }
};



vector<int> vec(3);

void input() {
	input_int_array(3, vec);
}

int solve() {
	auto max_it = max_element(all(vec));
	int max_v = *max_it;
	vec.erase(max_it);
	return vec[0]*vec[1]/2;
}

int main() {
	input();
	//solve();
	cout << solve() << endl;
}


Measured memory_bytes: 256