【算法竞赛入门经典】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>
相关文章推荐
- 【算法竞赛入门经典】回溯法与最优性剪枝条 例题7-6 UVa140
- 【算法竞赛入门经典】树形DP的状态转移方程优化 例题9-14 UVa1218
- 【算法竞赛入门经典】6.4.2用BFS求最短路 例题6-14 UVa816
- 【算法竞赛入门经典】多阶段决策问题 例题9-4 UVa116
- 算法竞赛入门经典第六章例题6-7 Trees on the level UVA - 122
- 算法竞赛入门经典第四章例题4-2 Hangman Judge UVA - 489
- 【算法竞赛入门经典】递归结构的动态规划 例题9-10 UVa1626
- 算法竞赛入门经典第六章例题6-3 Matrix Chain Multiplication UVA - 442
- 【算法竞赛入门经典】6.5[图的BFS] 例题6-20 UVa1599 (2)
- 【算法竞赛入门经典】动态规划初步 例题9-7 UVa11584
- 【算法竞赛入门经典】6.5[图的概念和拓扑序] 例题6-21 UVa506
- 【算法竞赛入门经典】树的最大独立集、树的唯一性问题 例题9-13 UVa1220
- 【算法竞赛入门经典】DAG上的动态规划 例题9-2 UVa437
- 【算法竞赛入门经典】动态规划初步 例题9-6 UVa11400
- 【算法竞赛入门经典】类LCS动态规划;指标函数分解 例题9-7 UVa1625
- 【算法竞赛入门经典】多阶段决策问题 例题9-5 UVa12563
- 【算法竞赛入门经典】7.5 路径寻找问题 例题7-9 UVa1601(1)
- 【算法竞赛入门经典】集合的动态规划;时间优化 例题9-16 UVa1252
- 算法竞赛入门经典第五章例题5-5 The SetStack Computer UVA - 12096
- 算法竞赛入门经典第五章例题5-7 Ugly Numbers UVA - 136