Good reference: http://www.cppblog.com/sdfond/archive/2009/07/31/91761.html
It is a classic coverage\dp compression problem. Initially I thought of dp[i][j] (i is row, j is col), but looks like it was not feasible to have a good dp transition function. Instead, the correct way to have dp[i][j] is: i is row still, but j is the state - state is binary representation which is said to be compressed (please check url above). It is just not that easy to figure out the key idea: valid state transition from row i to row i + 1.
First, a recursion procedure is used to compose all valid state transitions - bits by bits. And keep the transition restrictions in mind, we add two more full-state rows: row(0) and row(n+1) to make sure no tile exceeds the limit. At last, we pick row(n+1)(all-1-full-state)'s value which indicates a final valid state. And each dp move means a solution count accumulation.
Really interesting dp problem. And here is the AC code - since i'm still rookie, i just retyped almost everything in the url above :P
// POJ 2411 // http://www.cppblog.com/sdfond/archive/2009/07/31/91761.html #include <cstdio> #include <cstdlib> #include <vector> #include <algorithm> using namespace std; #define MAX_N 11 #define MAX_SIZE (1 << MAX_N) typedef unsigned long long uint64_t; vector<unsigned> rec[MAX_SIZE]; // s2 -> [s1]: for a dest state s2, recording all its previous valid s1 states uint64_t dp[MAX_N + 2][MAX_SIZE]; // Compose all valid s1->s2 transition by making composing every move valid // Note: a pattern of combinations by recurrence void dfs(int col, int s1, int s2, int w, uint64_t MaxState) { if (col >= w) { if (s1 <= MaxState && s2 <= MaxState) rec[s2].push_back(s1); // S1->S2 is a valid transition return; } dfs(col + 1, (s1 << 1) | 1, s2 << 1, w, MaxState); dfs(col + 1, s1 << 1, (s2 << 1) | 1, w, MaxState); dfs(col + 2, (s1 << 2) | 3, (s2 << 2) | 3, w, MaxState); } uint64_t calc(int h, int w) { uint64_t MaxState = (1 << w) - 1; // Reset rec for (int i = 0; i <= MaxState; i ++) rec[i].clear(); // DFS precalc - all valid state transitions dfs(0, 0, 0, w, MaxState); // Go DP dp[0][0] = 1; // row 0 added to start with for (int i = 1; i <= h + 1; i++) // each row for (uint64_t s = 0; s <= MaxState; s ++) // each state for (int k = 0; k < rec[s].size(); k ++) { dp[i][s] += dp[i - 1][rec[s][k]]; } return dp[h+1][MaxState]; } int main() { int w, h; while (scanf("%d %d", &h, &w), h && w) { if (h > w) std::swap(h, w); memset(dp, 0, sizeof(dp)); printf("%llu\n", calc(h, w)); } return 0; }