#include <stdio.h>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
#include <math.h>
#include <queue>
#include <functional>
#include <limits.h>
#include <numeric>

using namespace std;
typedef long long int ll;
#define rep(i,n) for(int i=0;i<(n);i++)
#define inf INT_MAX
#define linf LLONG_MAX
#define ninf INT_MIN
#define nlinf LLONG_MIN
#define mod 0
ll solve(int now,int h,int w,int a,int b,vector<vector<int>> board){
    int y=now/h,x=now%h;
    if(now==h*w)return 1;
    if(board[x][y]==1)return solve(now+1,h,w,a,b,board);
    board[x][y]=1;
    ll count=0;
    if(board[x+1][y]==0){
        board[x+1][y]=1;
        if(a>0)count+=solve(now+1,h,w,a-1,b,board);
        board[x+1][y]=0;
    }
    if(board[x][y+1]==0){
        board[x][y+1]=1;
        if(a>0)count+=solve(now+1,h,w,a-1,b,board);
        board[x][y+1]=0;
    }
    if(b>0)count+=solve(now+1,h,w,a,b-1,board);
    return count;
}
int main(){
    int h,w;cin>>h>>w;
    int a,b;cin>>a>>b;
    vector<vector<int>> board(h+1,vector<int>(w+1));
    rep(i,h+1)board[i][w]=1;
    rep(i,w+1)board[h][i]=1;
    cout<<solve(0,h,w,a,b,board)<<endl;
    return 0;
}
#include<iostream>
#include<bits/stdc++.h>
#include<math.h>
#include<vector>
#include<string>
#include<cstring>
#include<ctype.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <functional> // for less
using namespace __gnu_pbds;
using namespace std;

typedef tree<int, null_type, less<int>, rb_tree_tag,
			tree_order_statistics_node_update>
	new_data_set;
//   <<implemented_sorted_vector>>  new_data_set p;
//   <<insert_like_set>>           insert(key):log(n)
//<<accessing_iterator_by_index>> find_by_order(idx):log(n)
//	    <<accessing_by_value>>   order_of_key(key):log(n)
// << replace less<int> by greater<int> for descending order>>
// find(key), erase(find(key)) works the same!

#ifndef ONLINE_JUDGE // setting up print debugging
template<class K, class V>ostream& operator<<(ostream&s,const pair<K,V>&p){s<<'<'<<p.x<<", "<<p.y<<'>';return s;}
template<class T, class=typename T::value_type, class=typename enable_if<!is_same<T,string>::value>::type>
ostream& operator<<(ostream&s,const T&v){s<<'[';for(auto&x:v){s<<x<<", ";}if(!v.empty()){s<<"\b\b";}s<<']';return s;}
void __prnt(){cerr<<endl;} template<class T, class...Ts>void __prnt(T&&a,Ts&&...etc){cerr<<a<<' ';__prnt(etc...);}
#define print(...) __prnt(__VA_ARGS__)
#else
#define print(...)
#endif

typedef long long ll;
typedef long l;

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pb push_back
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define ERR(x) cout<<#x<<"="<<x<<endl
#define ERR2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl;
#define show(v) for(auto e: v) cout<<e<<" ";
#define showArr(A,n) for(int i=0;i<n;i++) cout<<A[i]<<" ";
#define PI 3.1415926535897932384626433832795
#define MOD 1000000007
#define mp make_pair
#define ff first
#define ss second
#define umpit unordered_map<ll,ll>::iterator
#define mpit map<ll,ll>::iterator
#define setit set<ll>::iterator
#define all(v) v.begin(),v.end()

ll ans = 0;
ll H,W,A,B;

void dfs(ll i, ll bit, ll A, ll B){
    if(i == H*W){
        ans++;
        return;
    }
    if(bit & 1LL << i){
        dfs(i+1, bit, A, B);
        return;
    }
    if(B){
        dfs(i+1, bit | 1LL << i, A, B-1);
    }
    if(A){
        if(i % W != W-1 && ~bit & 1LL << i+1){
            dfs(i+1, bit | 1LL << i | 1LL << i+1,  A-1, B);
        }
        if(i+W < H*W){
            dfs(i+1, bit | 1LL << i | 1LL << i+W,  A-1, B);
        }
    }
}


int main()
{
	int t;
	t = 1;
	int Case = 0;
	while(t--)
	{
        cin >> H >> W >> A >> B;
        dfs(0,0,A,B);
        cout << ans << endl;
	}
	return 0;
}
