您的位置:首页 > 其它

【算法竞赛入门经典】7.7 回溯法求连通块 例题7-14 UVa1602

2018-02-09 15:57 495 查看

【算法竞赛入门经典】7.7 回溯法求连通块 例题7-14 UVa1602

算法竞赛入门经典77 回溯法求连通块 例题7-14 UVa1602
例题UVa11211

分析

本题储存结构

样例实现代码

结果

例题UVa11211

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.



Input

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

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

分析。

很直截了当的一个回溯法求连通块的问题。从只有一个小格子开始,每次放置一个新的块上去,然后再判重。

最重要的是判重。鉴于每次旋转翻转或是加上格子之后可能出现的情况千奇百怪,所以为了使相同的组合成功判重,需要进行如下操作:

1.平移标准化

将每一种多边形的所有格子减去最小X,最小Y,这样就完成了平移的初始化。

2.旋转

实际上,一个多边形标准化之后,绕着原点进行旋转,每次旋转之后,多边形的每一个格子的坐标,y就是原来的-x,x就是原来的y,这是顺时针旋转的情况。

注意,旋转之后一定要平移标准化再用来判重。

3.翻转

实际上,沿着x轴或者y轴翻转的图形是同一个多边形。任意旋转180°就得到了另一个。所以,只需要翻转一个再标准化即可。例如,x不变,y变为-y。

本题储存结构

利用结构体Cell储存每一个组成多边形的格子。

利用set<Cell> ; poly来表示每个多边形,其中多边形的组成由Cell表示

利用set<poly> npoly来表示n个格子组成的多边形包含哪些多边形(poly)

注意:由于set的判重需求,需要重载<

样例实现代码

#include<iostream>
#include<set>
#include<algorithm>
#define maxn 11
using namespace std;
int ans[maxn][maxn][maxn];
const int dx[]{ -1,1,0,0 };
const int dy[]{ 0,0,-1,1 };
struct Cell {
int x;
int y;
Cell(int x=0,int y=0):x(x),y(y){}
bool operator < (const Cell &r) const{
return x < r.x || (x == r.x&&y < r.y);
}
};
typedef set<Cell>poly;
set<poly>npoly[maxn];
poly normalize(const poly &past) {
int minx = past.begin()->x, miny = past.begin()->y;
for (poly::iterator it = past.begin(); it != past.end(); it++) {
minx = min(minx, it->x);
miny = min(miny, it->y);
}
poly p;
for (poly::iterator it = past.begin(); it != past.end(); it++) {
p.insert(Cell((it->x) - minx, (it->y) - miny));
}
return p;
}
poly rotate(const poly &past) {
poly p;
for (poly::iterator it = past.begin(); it != past.end(); it++) {
p.insert(Cell(it->y, -(it->x)));
}
return normalize(p);
}
poly flip(const poly &past) {
poly p;
for (poly::iterator it = past.begin(); it != past.end(); it++) {
p.insert(Cell(it->x, -(it->y)));
}
return normalize(p);
}
void checkandinsert(const poly &past, const Cell &newc) {
poly p = past;
p.insert(newc);
p = normalize(p);
int n = p.size();
for (int i = 0; i < 4; i++) {
if (npoly
.count(p) != 0)
return;
p = rotate(p);
}
p = flip(p);
for (int i = 0; i < 4; i++) {
if (npoly
.count(p) != 0)
return;
p = rotate(p);
}
npoly
.insert(p);
}
void generate() {
poly start;
start.insert(Cell(0, 0));
npoly[1].insert(start);
for (int n = 2; n < maxn; n++) {
for (set<poly>::iterator it = npoly[n - 1].begin(); it != npoly[n - 1].end(); it++) {//每个npoly中的poly
for (poly::iterator itin = (*it).begin(); itin != (*it).end(); itin++) {//每个poly中的Cell
for (int dir = 0; dir < 4; dir++) {
Cell newc(itin->x + dx[dir], itin->y + dy[dir]);
if (it->count(newc) == 0)
checkandinsert(*it, newc);
}
}
}
}
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<poly>::iterator it = npoly
.begin(); it != npoly
.end(); it++) {
int maxx = 0, maxy = 0;
for (poly::iterator itin = (*it).begin(); itin != (*it).end(); itin++) {
maxx = max(maxx, itin->x);
maxy = max(maxy, itin->y);
}
if (min(maxx, maxy) < min(w, h) && max(maxx, maxy) < max(w, h))
cnt++;
}
ans
[w][h] = cnt;
}
}
}
}
int main() {
int n, w, h;
generate();
while (cin >> n >> w >> h) {
cout << ans
[w][h] << endl;
}
return 0;
}


结果<
a5bd
/h2>

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐