I was solving the **Little Elephant and T-Shirts** problem (https://www.codechef.com/problems/TSHIRTS/). With the help of the editorial I wrote the following code. But I have some doubts regarding it.

```
#include <bits/stdc++.h>
using namespace std;
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define rep(i,a,b) for(int i=a; i<b; i++)
#define ll long long
#define mod 1000000007
bool table[105][15];
ll dp[1030][105];
ll solve(int mask, int id, int n)
{
if(mask == ((1<<n)-1))
return dp[mask][id] = 1;
if(id == 101)
return 0;
if(dp[mask][id] != -1)
return dp[mask][id];
ll ways = 0;
ways += solve(mask,id+1,n);
rep(p,1,n+1)
{
if(mask&(1<<(p-1)))
continue;
if(table[id][p])
{
ways += solve(mask|(1<<(p-1)),id+1,n);
if(ways >= mod) ways -= mod;
}
}
return dp[mask][id] = ways;
}
int main()
{
int t;
cin >> t;
while(t--)
{
memset(table,false,sizeof(table));
memset(dp,-1,sizeof(dp));
int n;
cin >> n;
string s;
stringstream ss;
int x;
cin.ignore();
rep(i,1,n+1)
{
getline(cin,s);
ss << s;
while(ss >> x)
table[x][i] = true;
ss.clear();
}
// rep(i,0,10)
// {
// rep(j,0,10)
// cout << table[i][j] << " ";
// cout << "\n";
// }
cout << solve(0,1,n) << "\n";
}
return 0;
}
```

In the above code, there are two base cases which I am unable to understand. Not the base cases themselves but the way they are handled. In the first case when mask is equal to (1<<n)-1 we set dp[mask][id] as 1 and return it, why can’t we simply return 1 as dp[mask][id] = ways ultimately. Alright, then in the second case, when id is equal to 101 instead of setting dp[mask][id] as something we simply return 0. So do we do this just because we have to return something when we run out of T-shirts or is it important to return 0 only.

I think I still don’t understand memoization completely and how it actually works. Please help.