ACM题目————网格动物
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 ( 1n
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
输入n,w,h (1<=n<=10,1<=w,h<=n),求能放在w*h网格里的不同的n连块的个数(注意,平移,旋转,翻转后相同的算作同一种)。例如,2*4里的5连块有5种(第一行),而3*3里的8连块有以下3种(第二行)。
难点:
1.以每个格子来扩展。先枚举1连块,在对1连块的每个格子的4个方向进行扩展,枚举2连块,依次类推。
2.将n连块表示成n个格子的集合,将所有的n连块又表示成集合,判重任务交给set.
3.判重时要将n连块进行8个方向的旋转,并且每个n连块需要规范化(左下角的格子在(0,0)).
4.得到n连块后判断是否能放进w*h的网格中,由于n连块已经规范化,得到n连块的格子最大x,y坐标,即能盛下该n连块的长和宽。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | #include <cstdio> #include <set> #include <algorithm> using namespace std; #define maxn 10 // 代表一个网格节点 typedef struct cell { int x, y; //网格节点的坐标 // 构造函数 cell( int x, int y) { this ->x = x; this ->y = y; } bool operator < ( const struct cell& a) const { return x < a.x || (x == a.x && y < a.y); } }cell; // 一个Polyomino就是一堆cell的集合 typedef set<cell> poly; // poly_set[i]代表有i个cell的poly集合 set<poly> poly_set[maxn+1]; // answer[n][w][h]的答案 int answer[maxn+1][maxn+1][maxn+1]; void gen_poly(); void check_poly( const poly& this_p, cell& this_c); poly normalize(poly& p); poly rotate(poly& p); poly flip(poly& p); int main() { // 生成所有poly gen_poly(); // printf("here\n"); int n, w, h; while ( scanf ( "%d %d %d" , &n, &w, &h) == 3) { printf ( "%d\n" , answer[n][w][h]); } return 0; } int dic_x[4] = {-1,0,1,0}; int dic_y[4] = {0,1,0,-1}; // 生成所有poly void gen_poly() { for ( int i = 1; i <= maxn; i++) poly_set[i] = set<poly>(); // 先生成有1个cell的poly poly p1; p1.insert(cell(0,0)); poly_set[1].insert(p1); // 分别根据有i-1个cell的poly集合来生成有i个cell的poly集合 for ( int i = 2; i <= maxn; i++) { // 对每个poly中的每个cell尝试在不同的四个方向增加一个cell for (set<poly>::iterator p = poly_set[i-1].begin(); p != poly_set[i-1].end(); p++) { for (poly::const_iterator q = p->begin(); q != p->end(); q++) { for ( int j = 0; j < 4; j++) { cell new_c(q->x+dic_x[j], q->y+dic_y[j]); // cell new_c; if (p->find(new_c) == p->end()) { // 检查形成的这个poly是否存在,如果不存在就加入 check_poly(*p, new_c); } } } } } // 对所有n,w,h生成答案 for ( int i = 1; i <= maxn; i++) { for ( int w = 1; w <= i; w++) { for ( int h = 1; h <= i; h++) { int count = 0; for (set<poly>::iterator p = poly_set[i].begin(); p != poly_set[i].end(); p++) { int max_x = p->begin()->x, max_y = p->begin()->y; for (poly::iterator q = p->begin(); q != p->end(); q++) { if (max_x < q->x) max_x = q->x; if (max_y < q->y) max_y = q->y; } if (min(max_x, max_y) < min(w, h) && max(max_x, max_y) < max(w, h)) { count++; } } /* if(count != 0) printf("answer[%d][%d][%d] = %d\n", i, w, h, count); */ answer[i][w][h] = count; } } } } // 检查形成的这个poly加上这个cell是否存在,如果不存在就加入 void check_poly( const poly& this_p, cell& this_c) { poly p = this_p; p.insert(this_c); // 规范化到最小点为(0,0) p = normalize(p); int n = p.size(); // 检查旋转的8个方向是否存在,如果不存在就加入到poly集合 for ( int i = 0; i < 4; i++) { if (poly_set[n].find(p) != poly_set[n].end()) return ; // 对该poly向右旋转90度 p = rotate(p); } // 将该poly向下反转180度 p = flip(p); for ( int i = 0; i < 4; i++) { if (poly_set[n].find(p) != poly_set[n].end()) return ; // 对该poly向右旋转90度 p = rotate(p); } poly_set[n].insert(p); } // 规范化到最小点为(0,0) poly normalize(poly& p) { poly this_p; int min_x = p.begin()->x, min_y = p.begin()->y; for (poly::iterator q = p.begin(); q != p.end(); q++) { if (q->x < min_x) min_x = q->x; if (q->y < min_y) min_y = q->y; } for (poly::iterator q = p.begin(); q != p.end(); q++) { this_p.insert(cell(q->x-min_x,q->y-min_y)); } return this_p; } // 对该poly向右旋转90度 poly rotate(poly& p) { poly this_p; for (poly::iterator q = p.begin(); q != p.end(); q++) { this_p.insert(cell(q->y,-q->x)); } return normalize(this_p); } // 将该poly向下反转180度 poly flip(poly& p) { poly this_p; for (poly::iterator q = p.begin(); q != p.end(); q++) { this_p.insert(cell(q->x,-q->y)); } return normalize(this_p); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了