#include <iostream>
#include <map>
using namespace std;
struct place{ //座標を格納する構造体
int w; //幅
int h; //高さ
bool operator<(const place& pl) const {
return (w==pl.w)?(h<pl.h):(w<pl.w);
}
};
bool DiscoveryMap(map<place,int> memo,place element);
//mapに要素が含まれるか調べる
int solve(place now, map<place,int> *memo);
int main()
{
map<place,int> memo;//メモ化再帰用
int w,h;
int answer;
place goal;
cin >> w >> h;
goal.w = w;
goal.h = h;
answer = solve(goal,&memo);
cout << answer;
return 0;
}
int solve(place now, map<place,int> *memo)
{
place next1 , next2;
if( now.w == 1 || now.h == 1 ) //座標が壁際であれば
return 1; //1を返す
if( DiscoveryMap(*memo,now) )//メモの中にあれば
return (*memo)[now]; //その値を返す
next1.w = now.w;
next1.h = now.h - 1; //一個下の座標
next2.w = now.w - 1; //一個左の座標
next2.h = now.h;
(*memo)[now] = solve(next1, memo) + solve(next2, memo);
//メモに答えを格納
return (*memo)[now];
}
bool DiscoveryMap(map<place,int>memo,place element)
{
auto ite = memo.find(element);
return ite != memo.end();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWFwPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwogCnN0cnVjdCBwbGFjZXsgICAvL+W6p+aomeOCkuagvOe0jeOBmeOCi+ani+mAoOS9kwogICAgaW50IHc7ICAgICAgLy/luYUKICAgIGludCBoOyAgICAgIC8v6auY44GVCiAgICBib29sIG9wZXJhdG9yPChjb25zdCBwbGFjZSYgcGwpIGNvbnN0IHsKICAgICAgICByZXR1cm4gKHc9PXBsLncpPyhoPHBsLmgpOih3PHBsLncpOwogICAgfQp9OwogCmJvb2wgRGlzY292ZXJ5TWFwKG1hcDxwbGFjZSxpbnQ+IG1lbW8scGxhY2UgZWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9tYXDjgavopoHntKDjgYzlkKvjgb7jgozjgovjgYvoqr/jgbnjgosKaW50IHNvbHZlKHBsYWNlIG5vdywgbWFwPHBsYWNlLGludD4gKm1lbW8pOwogCmludCBtYWluKCkKewogICAgbWFwPHBsYWNlLGludD4gbWVtbzsvL+ODoeODouWMluWGjeW4sOeUqAogICAgaW50IHcsaDsKICAgIGludCBhbnN3ZXI7CiAgICBwbGFjZSBnb2FsOwogICAgCiAgICBjaW4gPj4gdyA+PiBoOwogICAgCiAgICBnb2FsLncgPSB3OwogICAgZ29hbC5oID0gaDsKIAogICAgYW5zd2VyID0gc29sdmUoZ29hbCwmbWVtbyk7CiAgICBjb3V0IDw8IGFuc3dlcjsKICAgIHJldHVybiAwOwp9CiAKaW50IHNvbHZlKHBsYWNlIG5vdywgbWFwPHBsYWNlLGludD4gKm1lbW8pCnsKICAgIHBsYWNlIG5leHQxICwgbmV4dDI7CiAgICBpZiggbm93LncgPT0gMSB8fCBub3cuaCA9PSAxICkgIC8v5bqn5qiZ44GM5aOB6Zqb44Gn44GC44KM44GwCiAgICAgICAgcmV0dXJuIDE7ICAgICAgICAgICAgICAgICAgIC8vMeOCkui/lOOBmQogICAgCiAgICBpZiggRGlzY292ZXJ5TWFwKCptZW1vLG5vdykgKS8v44Oh44Oi44Gu5Lit44Gr44GC44KM44GwCiAgICAgICAgcmV0dXJuICgqbWVtbylbbm93XTsgICAgLy/jgZ3jga7lgKTjgpLov5TjgZkKICAgIAogICAgbmV4dDEudyA9IG5vdy53OwogICAgbmV4dDEuaCA9IG5vdy5oIC0gMTsgICAgLy/kuIDlgIvkuIvjga7luqfmqJkKICAgIAogICAgbmV4dDIudyA9IG5vdy53IC0gMTsgICAgLy/kuIDlgIvlt6bjga7luqfmqJkKICAgIG5leHQyLmggPSBub3cuaDsKICAgIAogICAgKCptZW1vKVtub3ddID0gc29sdmUobmV4dDEsIG1lbW8pICsgc29sdmUobmV4dDIsIG1lbW8pOwogICAgICAgIC8v44Oh44Oi44Gr562U44GI44KS5qC857SNCiAgICByZXR1cm4gKCptZW1vKVtub3ddOwp9CiAKYm9vbCBEaXNjb3ZlcnlNYXAobWFwPHBsYWNlLGludD5tZW1vLHBsYWNlIGVsZW1lbnQpCnsKICAgIGF1dG8gaXRlID0gbWVtby5maW5kKGVsZW1lbnQpOwogICAgcmV0dXJuIGl0ZSAhPSBtZW1vLmVuZCgpOwp9