int n, m; // f[i][j] 表示 1 x 2 长方形从 i-1 列捅到 i 列,且这种参差不齐的状态可以表示为 j 的所有方案数。j 看做一个二进制数,如果横着的长方形从 i-1 列捅到 i 列,该位记为 1,否则记为 0 longlong f[N][M]; // st[i] 表示 i 这种状态是否合法,例如 (1010)2 这种状态 st[10] 不合法,因为这样的列中连续是空的格子的长度为奇数,无法被竖着的 2 x 1 长方形填满 bool st[M];
intmain(){ int n, m; while (cin >> n >> m, n || m) { memset(f, 0, sizeof f); // 先预处理处所有参差不齐的状态,那些合法,那些非法 for (int i = 0; i < 1 << n; i++) { st[i] = true; int cnt = 0; for (int j = 0; j < n; j++) { if (i >> j & 1) { if (cnt & 1) st[i] = false; cnt = 0; } else cnt++; } if (cnt & 1) st[i] = false; }
f[0][0] = 1; // 遍历每一列 for (int i = 1; i <= m; i++) { // 遍历当前列上可能的参差不齐的状态 for (int j = 0; j < 1 << n; j++) { // 遍历前一列上可能的参差不齐的状态 for (int k = 0; k < 1 << n; k++) { // 转移条件:同一行上,前一列横着的长方形不能捅到当前列;上一列连续空的位置长度不能为奇数。当前列对应位置放没放对应 j 这个二进制状态,因为是 1 x 2 的长方形,所以上一列所有 j 对应的位置都是放着的,因此要 j | k 取并集 if ((j & k) == 0 && st[j | k]) { f[i][j] += f[i - 1][k]; } } } } cout << f[m][0] << endl; } }
constint N = 310; int n, m; int h[N][N]; int f[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; intdp(int x, int y){ int &v = f[x][y]; if (v != -1) return v; v = 1; for (int i = 0; i < 4; i++) { int a = x + dx[i], b = y + dy[i]; if (a >= 1 && a <= n && b >= 1 && b <= m && h[a][b] < h[x][y]) { v = max(v, dp(a, b) + 1); } } return v; }
intmain(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { scanf("%d", &h[i][j]); } } memset(f, -1, sizeof f); int res = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { res = max(res, dp(i, j)); } } printf("%d\n", res); return0; }