Here we have a box that is 4 * 7 and it can be filled with rectangles that are either 1 * 2 or 2 * 1. This depiction is from the book Competitive Programmer's Handbook.
To solve this problem most efficiently, the book mentions using the parts that can be in a particular row:
Since there are 4 things in this set, the maximum unique rows we can have is 4^m, where m is the number of columns. From each constructed row, we construct the next row such that it is valid. Valid means we cannot have vertical fragments out of order. Only if all vertical "caps" in the top row correspond to vertical "cups" in the bottom row and vice versa is the solution valid. (Obviously for the horizontal fragments, their construction is restricted in row creation itself, so it is not possible for there to be inter-row discrepancy here.)
The book then says this:
Since a row consists of m characters and there are four choices for each character, the number of distinct rows is at most 4^m. Thus, the time complexity of the solution is O(n4^{2m}) because we can go through the O(4^m) possible states for each row, and for each state, there are O(4^m) possible states for the previous row.
Everything is fine until the last phrase, "there are O(4^m) possible states for the previous row." Why do we only consider the previous row? There are more rows, and this time complexity should consider the entire problem, not just the previous row, right?
Here is my ad hoc C++ implementation for 2 by n matrix, which would not work in this case, but I was trying to abstract it:
int ways[251];
int f(int n){
if (ways[n] != 1) return ways[n];
return (ways[n] = f(n-1) + f(n-2));
}
int main(){
ways[0] = 1;
ways[1] = 1;
for (int i = 2; i <= 250; i++){
ways[i] = -1;
cout << f(250) << '\n';
}
}