UVa1602/LA3224 Lattice Animals
UVa1602/LA3224 Lattice Animals
- 题目链接
- 题意
- 输入格式
- 输出格式
- 分析
- AC 代码
题目链接
本题是2004年icpc欧洲区域赛东北欧赛区的L题
题意
输入n、w、h(1≤n≤10,1≤w,h≤n),求能放在 w×hw\times hw×h 网格里的不同的 n 连块的个数(注意,平移、旋转、翻转后相同的算作同一种,可以将平移、旋转、翻转组合变换)。如下图所示,2×42\times 42×4 里的 5 连块有 5 种(第一行),而 3×33\times 33×3 里的 8 连块有 3 种(第二行)。
输入格式
输入包含多组数据,每组数据只有一行,包含三个正整数n、w、h。
输出格式
对于每组测试数据,输出一行,输出 w×hw\times hw×h 网格里的不同的 n 连块的个数。
分析
由于 n 比较小,可以先不管网格限制,直接递推计算出不同的 1、2、…、n 连块,计算出 k 连块之后枚举每个 k 连块的每一个格子,尝试在这个格子的上下左右添加格子得到 k+1 连块,并进行平移、旋转、翻转组合变换来和已经存在的 k+1 连块判重。
计算出所有不同的 1、2、…、n 连块后,就可以打表得出所有的结果,然后读入n、w、h就能直接输出答案。
AC 代码
#include <iostream>
#include <algorithm>
using namespace std;#define T 4660
#define N 11
int f[N][N+1][N], t[N], n, w, h;struct node {int p[N], w, h;bool eq(const node &e, const int n) const {for (int i=0; i<n; ++i) if (p[i] != e.p[i]) return false;return true;}node rotate(const int n) const {node t; t.w = h; t.h = w;for (int i=0; i<n; ++i) {int r = p[i]&15, c = h-1 - (p[i]>>4);t.p[i] = r<<4 | c;}sort(t.p, t.p+n);return t;}node flip_h(const int n) const {node t; t.w = w; t.h = h;for (int i=0; i<n; ++i) {int r = h-1 - (p[i]>>4), c = p[i]&15;t.p[i] = r<<4 | c;}sort(t.p, t.p+n);return t;}node flip_v(const int n) const {node t; t.w = w; t.h = h;for (int i=0; i<n; ++i) {int r = p[i]>>4, c = w-1 - (p[i]&15);t.p[i] = r<<4 | c;}sort(t.p, t.p+n);return t;}
} s[N][T];bool exist(const int n, const int t) {node e = s[n][t-1];for (int i=0; i<4; ++i, e = e.rotate(n)) {node h = e.flip_h(n), v = e.flip_v(n);for (int j=t-2; j>=0; --j) {const node &f = s[n][j];if (e.w != f.w || e.h != f.h) continue;if (e.eq(f, n) || h.eq(f, n) || v.eq(f, n)) return true;}}return false;
}void add(const node &e, int n, int v) {int &c = t[n], k = lower_bound(e.p, e.p+n-1, v) - e.p;if (k < n-1 && e.p[k] == v) return;node& f = s[n][c++]; f.w = e.w; f.h = e.h;for (int i=0; i<k; ++i) f.p[i] = e.p[i];for (int i=n-1; i>k; --i) f.p[i] = e.p[i-1];f.p[k] = v;if (exist(n, c)) --c;
}void generate() {for (int n=1; n<N; ++n) {if (n > 1) {for (int &k = t[n] = 0, i=t[n-1]-1; i>=0; --i) {const node& e = s[n-1][i];for (int j=n-2; j>=0; --j) {int r = e.p[j]>>4, c = e.p[j]&15;if (r == 0) {node& f = s[n][k++]; f.w = e.w; f.h = e.h+1;for (int x=n-1; x>0; --x) f.p[x] = e.p[x-1] + 16;f.p[0] = c;if (exist(n, k)) --k;} else if (r > 0) add(e, n, e.p[j] - 16);if (r == e.h-1) {node& f = s[n][k++]; f.w = e.w; f.h = e.h+1;for (int x=n-2; x>=0; --x) f.p[x] = e.p[x];f.p[n-1] = e.p[j] + 16;if (exist(n, k)) --k;} else if (r < e.h-1) add(e, n, e.p[j] + 16);if (c == 0) {node& f = s[n][k++]; f.w = e.w+1; f.h = e.h;for (int x=0; x<j; ++x) f.p[x] = e.p[x] + 1;for (int x=n-1; x>j; --x) f.p[x] = e.p[x-1] + 1;f.p[j] = e.p[j];if (exist(n, k)) --k;} else if (c > 0) add(e, n, e.p[j] - 1);if (c == e.w-1) {node& f = s[n][k++]; f.w = e.w+1; f.h = e.h;for (int x=0; x<=j; ++x) f.p[x] = e.p[x];for (int x=n-2; x>j; --x) f.p[x+1] = e.p[x];f.p[j+1] = e.p[j] + 1;if (exist(n, k)) --k;} else add(e, n, e.p[j] + 1);}}} else s[1][0].w = s[1][0].h = 1, s[1][0].p[0] = 0, t[1] = 1;for (int h=1; h<=n; ++h) for (int w=h; w<=n; ++w) {int &a = f[w][h][n] = 0, &b = f[h][w][n] = 0;if (w*h >= n) for (int i=t[n]-1; i>=0; --i) {int hi = min(s[n][i].w, s[n][i].h), wi = max(s[n][i].w, s[n][i].h);if (hi <= h && wi <= w) {if (h < w) ++b;++a;}}}}
}int main() {generate();while (cin >> n >> w >> h) cout << f[w][h][n] << endl;return 0;
}