【POJ 2411】 Mondriaan's Dream
【题目链接】
【算法】
很明显,我们可以用状态压缩动态规划解决此题
f[n][m]表示n-1行已经放满,第n行状态为m的合法的方案数
状态转移方程很好推
注意这题时限较紧,注意加一些小优化
【代码】
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; #define MAXN 12 long long n,m; long long f[MAXN][1<<MAXN],ans[MAXN][MAXN]; template <typename T> inline void read(T &x) { long long f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } inline bool ok(long long s) { long long i = 0; while (i < m) { if (s & (1 << i)) { if (!(s & (1 << (i + 1)))) return false; i += 2; continue; } i++; } return true; } inline bool check(long long now,long long last) { long long i = 0; while (i < m) { if (!(last & (1 << i))) { if (!(now & (1 << i))) return false; i++; continue; } else { if ((now & (1 << i)) && (now & (1 << (i + 1))) && (last & (1 << (i + 1)))) { i += 2; continue; } if (!(now & (1 << i))) { i++; continue; } return false; } } return true; } inline void solve(long long n,long long m) { long long i,j,k, MASK = (1 << m) - 1; for (i = 0; i <= MASK; i++) if (ok(i)) f[1][i] = 1; else f[1][i] = 0; for (i = 2; i <= n; i++) { for (j = 0; j <= MASK; j++) { f[i][j] = 0; for (k = 0; k <= MASK; k++) { if (check(j,k)) f[i][j] += f[i-1][k]; } } } ans[n][m] = ans[m][n] = f[n][MASK]; writeln(f[n][MASK]); } int main() { memset(ans,255,sizeof(ans)); while (true) { read(n); read(m); if (!n && !m) break; if (n & 1 && m & 1) ans[n][m] = ans[m][n] = 0; if (ans[n][m] != -1) { writeln(ans[n][m]); continue; } if (n < m) swap(n,m); solve(n,m); } return 0; }