Count Ways to Build House of Cards
Given N playing cards, the task is to return the number of distinct house of cards we can build using all N cards. A house of cards meets the following conditions:
- A house of cards consists of one or more rows of triangles and horizontal cards.
- Triangles are created by leaning two cards against each other.
- One card must be placed horizontally between all adjacent triangles in a row.
- Any triangle on a row higher than the first must be placed on a horizontal card from the previous row.
- Each triangle is placed in the leftmost available spot in the row.
Note: Two houses of cards are considered distinct if there exists a row where the two houses contain a different number of cards.

Examples:
Input: N = 2
Output: 1
Explanation: Only one house of cards having 1 row can be built using 2 cards.Input: N = 16
Output: 2
Explanation: The two valid houses of cards are shown.
The third house of cards in the diagram is not valid because the rightmost triangle on the top row is not placed on top of a horizontal card.
Approach: To solve the problem, follow the below idea:
The problem can be solved using Dynamic Programming. Maintain a recursive function solve(n, prevTriangles) which returns the number of possible houses if we have n cards and the previous row had prevTriangles. In each row, we know that the first triangle will need 2 cards and every subsequent triangle will need 3 cards. Now in every row, start making triangles one by one and after making each triangle, move to the next row with the remaining cards. At any point, if we reach a row with 0 cards, then we have constructed a valid house so increment ans by 1. After all the recursive calls, return ans.
The above recursive calls can be momoized using a dp[][] table such that dp[i][j] stores the number of ways to construct a valid house using i cards such that the previous row had j triangles.
Below is the implementation of the above algorithm:
#include <bits/stdc++.h>
using namespace std;
int solve(int n, int prevTriangles,
vector<vector<int> >& dp)
{
// If we have zero cards left, then we have successfully
// constucted a house, so return 1
if (n == 0)
return 1;
// If we have less than two cards or the last row had
// only triangle, then return 0
if (n < 2 || prevTriangles == 1)
return 0;
// Check if the result has been previously calculated
if (prevTriangles != 1e9 && dp[n][prevTriangles] != -1)
return dp[n][prevTriangles];
int currCards = 2, currTriangles = 1;
int res = 0;
// Iterate till we have cards left and the number of
// triangles in current row is less than the previous
// row
while (currCards <= n
&& currTriangles < prevTriangles) {
res += solve(n - currCards, currTriangles, dp);
currTriangles += 1;
currCards += 3;
}
// Store the result in the dp table
if (prevTriangles != 1e9)
dp[n][prevTriangles] = res;
return res;
}
// function to count the number of ways to construct a house
// using n cards
int houseOfCards(int n)
{
vector<vector<int> > dp(n + 1, vector<int>(n + 1, -1));
return solve(n, 1e9, dp);
}
int main()
{
// Sample Input
int n = 16;
cout << houseOfCards(n);
}
Output
2
Time Complexity: O(N*N), where N is the total number of cards.
Auxiliary Space: O(N * N)