您的位置:首页 > 其它

1602 - Lattice Animals

2015-07-12 19:36 381 查看
Lattice animal is a set of connected sites on a lattice. Lattice animals on a square lattice are especially popular subject of study and are also known as polyominoes. Polyomino is usually represented as a set of sidewise connected squares. Polyomino with n squares is called n-polyomino. In this problem you are to find a number of distinct free n-polyominoes that fit into rectangle w×h. Free polyominoes can be rotated and flipped over, so that their rotations and mirror images are considered to be the same. For example, there are 5 different pentominoes (5-polyominoes) that fit into 2×4 rectangle and 3 different octominoes (8-polyominoes) that fit into 3×3 rectangle.

Input

The input file contains several test cases, one per line. This line consists of 3 integer numbers n, w, and h ( 1n10, 1w, hn).

Output

For each one of the test cases, write to the output file a single line with a integer number – the number of distinct free n-polyominoes that fit into rectangle w×h.

Sample Input

5 1 4

5 2 4

5 3 4

5 5 5

8 3 3

Sample Output

0

5

11

12

3

我有话说:

这道题在细节上的处理是比较繁琐的。如果没有网上细致的题解,我觉得完成是很成问题的。

先是基本的思路,依靠set这个强大的工具枚举,储存,检验。把一个个单位格子编上坐标,和常见的坐标轴一样。然后就是从每个已有的格子开始在旁边不断地添上一块。并进行检验。所以难免要枚举所有的情况各种的n,w,h。最后输出。

请先把所有的外函数都先看完,并清楚它们的功能。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;

struct Cell {
int x, y;
Cell(int x=0, int y=0):x(x),y(y) {};
bool operator < (const Cell& rhs) const {
return x < rhs.x || (x == rhs.x && y < rhs.y);
}
};

typedef set<Cell> Polyomino;

#define FOR_CELL(c, p) for(Polyomino::const_iterator c = (p).begin(); c != (p).end(); ++c)//定义,否则写写实在太麻烦

inline Polyomino normalize(const Polyomino &p) {//找到最小的x,y
int minX = p.begin()->x, minY = p.begin()->y;
FOR_CELL(c, p) {
minX = min(minX, c->x);
minY = min(minY, c->y);
}
Polyomino p2;
FOR_CELL(c, p)
p2.insert(Cell(c->x - minX, c->y - minY));//以此为坐标轴重新确立坐标,可以看成平移
return p2;
}

inline Polyomino rotate(const Polyomino &p) {//顺时针旋转
Polyomino p2;
FOR_CELL(c, p)
p2.insert(Cell(c->y, -c->x));
return normalize(p2);
}

inline Polyomino flip(const Polyomino &p) {//上下做镜面对称变换
Polyomino p2;
FOR_CELL(c, p)
p2.insert(Cell(c->x, -c->y));
return normalize(p2);
}

const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
const int maxn = 10;

set<Polyomino> poly[maxn+1];//已有的联通块
int ans[maxn+1][maxn+1][maxn+1];

//添加一个联通块,并判断他是不是新的联通块,如果是的话,加入polyonimo集合
void check_polyomino(const Polyomino& p0, const Cell& c) {
Polyomino p = p0;
p.insert(c);
p = normalize(p);

int n = p.size();
for(int i = 0; i < 4; i++) {
if(poly
.count(p) != 0) return;
p = rotate(p);
}
p = flip(p);
for(int i = 0; i < 4; i++) {
if(poly
.count(p) != 0) return;
p = rotate(p);
}
poly
.insert(p);
}

void generate() {
Polyomino s;
s.insert(Cell(0, 0));
poly[1].insert(s);

// generate生成
for(int n = 2; n <= maxn; n++) {
for(set<Polyomino>::iterator p = poly[n-1].begin(); p != poly[n-1].end(); ++p)
FOR_CELL(c, *p)
for(int dir = 0; dir < 4; dir++) {
Cell newc(c->x + dx[dir], c->y + dy[dir]);
if(p->count(newc) == 0) check_polyomino(*p, newc);//如果和原来的p中任意一点都不重合的话,至少来看在目前是有效的。不过要进一步检验
}
}//枚举

// precompute answers
//预计算的答案
for(int n = 1; n <= maxn; n++)
for(int w = 1; w <= maxn; w++)
for(int h = 1; h <= maxn; h++) {
int cnt = 0;
for(set<Polyomino>::iterator p = poly
.begin(); p != poly
.end(); ++p) {
int maxX = 0, maxY = 0;
FOR
4000
_CELL(c, *p) {
maxX = max(maxX, c->x);
maxY = max(maxY, c->y);
}
if(min(maxX, maxY) < min(h, w) && max(maxX, maxY) < max(h, w))//最理想的符合状态
++cnt;
}
ans
[w][h] = cnt;
}
}

int main() {
generate();

int n, w, h;
while(scanf("%d%d%d", &n, &w, &h) == 3) {
printf("%d\n", ans
[w][h]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: