Problem (Black 1946, Gamow–Stern 1958). Remove two diagonally opposite corners of a chessboard. Can the remaining 62 squares be tiled by 31 dominoes?

Answer. No: every domino covers one white and one black square, but both removed corners have the same colour, leaving 32 of one colour and 30 of the other. Colouring arguments are the main tool for “impossible” tilings; for “possible” ones, a construction or a counting DP.

QuestionAnswerTool
minus two opposite corners, dominoesimpossiblechessboard colouring
minus one white and one black square, dominoesalways possible (Gomory)Hamiltonian cycle of the board
by stripspossible iff or colouring by
minus one square, stripspossible iff the hole is at (0-indexed)two diagonal 3-colourings
minus any square, L-trominoesalways possibledivide and conquer, see Tromino Tiling
number of domino tilings of profile DP, Kasteleyn’s formula
domino tilings of a region with holescount by profile DP ; existence = perfect matchingProfile DP, Bipartite Matching
// Number of domino tilings of a grid with blocked cells '#', broken-profile DP in O(n m 2^m).
// Bit j of the mask: the next unprocessed cell in column j is already covered.
ll dominoTilings(const vector<string>& g) {
    int n = sz(g), m = sz(g[0]); vector<ll> dp(1 << m, 0), nd(1 << m); dp[0] = 1;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) {
        fill(all(nd), 0);
        for (int mask = 0; mask < (1 << m); mask++) if (ll v = dp[mask]) {
            if (mask >> j & 1) { nd[mask ^ 1 << j] += v; continue; }                 // covered from above or the left
            if (g[i][j] == '#') { nd[mask] += v; continue; }
            if (i + 1 < n && g[i + 1][j] != '#') nd[mask | 1 << j] += v;             // vertical domino
            if (j + 1 < m && !(mask >> (j + 1) & 1) && g[i][j + 1] != '#') nd[mask | 1 << (j + 1)] += v;   // horizontal
        }
        swap(dp, nd);
    }
    return dp[0];
}
 
// Can the free cells ('.') be tiled by 1 x k strips? Backtracking on the first free cell.
bool stripTile(vector<string>& g, int k) {
    int n = sz(g), m = sz(g[0]), r = -1, c = -1;
    for (int i = 0; i < n && r < 0; i++) for (int j = 0; j < m; j++) if (g[i][j] == '.') { r = i, c = j; break; }
    if (r < 0) return true;
    for (int dir = 0; dir < 2; dir++) {                  // the first free cell must be the left or top end of its strip
        bool ok = true;
        for (int t = 0; t < k && ok; t++) { int x = r + dir * t, y = c + (1 - dir) * t; ok = x < n && y < m && g[x][y] == '.'; }
        if (!ok) continue;
        for (int t = 0; t < k; t++) g[r + dir * t][c + (1 - dir) * t] = '#';
        bool res = stripTile(g, k);
        for (int t = 0; t < k; t++) g[r + dir * t][c + (1 - dir) * t] = '.';
        if (res) return true;
    }
    return false;
}

The number of domino tilings of an board is given by Kasteleyn’s formula (Kasteleyn; Temperley and Fisher, 1961), proved with Pfaffians:

stated here without proof; it agrees with dominoTilings for all (, and it grows like with Catalan’s constant ).