UVA-1602 Lattice Animals 搜索问题(打表+set)

题目链接 https://vjudge.net/problem/UVA-1602

紫书的一道例题,跟之前的很多题目有很多不同。

本题不像是一般的dfs或bfs这样的搜索套路,而是另一种枚举思路。

题意:

输入n、 w、 h(1≤n≤10,1≤w,h≤n),求能放在w*h网格里的不同的n连块的个数(平移、 旋转、 翻转后相同的图形算作同一种)。

思路:

思路很明确,生成图形后判重,加入重复表或弃掉。

本题的重点就在生成和判重。

  我的思路:

连通块的生成:通过维护一个int open[10][10]={0}, vis[10][10]来记录可连通的许多块和已走块,在确定下一步时向open中添加新块的连通块(自加),在回溯时删除对应的连通块(自减)。

连通块的判重:通过move()函数平移连通块的每个块使之标准化,rote()函数旋转连通块顺时针90°,mirror()函数生成连通块镜像判断重复,同时插入重复表中。

  参考思路(紫书);

连通块的生成:通过向n-1个块的重复表的各连通块中加入新块生成n个块的新图。

连通块的判重:同上,只是函数名有变。

思路二:

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <set>
  5 using namespace std;
  6 struct Cell{
  7     int x, y;
  8     Cell(int x=0, int y=0):x(x),y(y) {}
  9     bool operator < (const Cell &a) const{
 10         return x<a.x || (x==a.x && y<a.y);
 11     }
 12 };
 13 int maxn=10, dir[4][2]={0,1,0,-1,1,0,-1,0};
 14 int n, h, w, ans[11][11][11]={0}, vis[11][11];
 15 typedef set<Cell> Poly;
 16 set<Poly> state[11];
 17 
 18 inline Poly move(Poly &p){
 19     int mx=maxn, my=maxn;
 20     Poly p2;
 21     for (Poly::iterator c=p.begin(); c!=p.end(); ++c){
 22         if (mx>c->x) mx=c->x;
 23         if (my>c->y) my=c->y;
 24     }
 25     for (Poly::iterator c=p.begin(); c!=p.end(); ++c)
 26         p2.insert(Cell(c->x-mx, c->y-my));
 27     return p2;
 28 }
 29 
 30 inline Poly rote(Poly &p){
 31     Poly p2;
 32     for (Poly::iterator c=p.begin(); c!=p.end(); ++c)
 33         p2.insert(Cell(c->y, -(c->x)));
 34     return move(p2);
 35 }
 36 
 37 inline Poly mirror(Poly &p){
 38     Poly p2;
 39     for (Poly::iterator c=p.begin(); c!=p.end(); ++c)
 40         p2.insert(Cell(c->x, -(c->y)));
 41     return move(p2);
 42 }
 43 
 44 void check(Poly p, Cell &c){
 45     p.insert(c);
 46     p=move(p);
 47     if (state[n].count(p)) return;
 48     for (int i=0; i<3; i++){
 49         p=rote(p);
 50         if (state[n].count(p)) return;
 51     }
 52     p=mirror(p);
 53     if (state[n].count(p)) return;
 54     for (int i=0; i<3; i++){
 55         p=rote(p);
 56         if (state[n].count(p)) return;
 57     }
 58     p=move(p);
 59     state[n].insert(p);
 60 }
 61 
 62 void pre(void){
 63     Poly p;
 64     p.insert(Cell(0, 0));
 65     state[1].insert(p);
 66     
 67     for (n=2; n<=maxn; n++)
 68         for (set<Poly>::iterator p=state[n-1].begin(); p!=state[n-1].end(); ++p)
 69             for (Poly::iterator c=(*p).begin(); c!=(*p).end(); ++c)
 70                 for (int j=0; j<4; j++){
 71                     Cell nc((c->x)+dir[j][0], (c->y)+dir[j][1]);
 72                     if (!(p->count(nc))) check(*p, nc);
 73                 }
 74     for (n=2; n<=maxn; n++){
 75         for (set<Poly>::iterator p=state[n].begin(); p!=state[n].end(); ++p){
 76             int maxx=0, maxy=0; 
 77             for (Poly::iterator c=(*p).begin(); c!=(*p).end(); ++c){
 78                 if (maxx<(c->x)) maxx=(c->x);
 79                 if (maxy<(c->y)) maxy=(c->y);
 80             }
 81             if (maxx>maxy) ans[n][maxx+1][maxy+1]++;
 82             else ans[n][maxy+1][maxx+1]++;
 83         }
 84     }
 85 }
 86 
 87 int show(int w, int h){
 88     int spr=(w>h)?w:h, mnr=(w!=spr)?w:h, re=0;
 89     for (int i=1; i<=spr; i++)
 90         for (int j=1; j<=mnr; j++)
 91             if (i>=j) re+=ans[n][i][j];
 92     return re;
 93 }
 94 
 95 int main(void){
 96     pre();
 97     
 98     while(scanf("%d%d%d", &n, &h, &w)==3 && n) 
 99         printf("%d
", (n==1)?1:show(w, h));
100 
101     return 0;
102 }

因为思路一的代码bug还没解决,等AC了就交上来。: )

原文地址:https://www.cnblogs.com/tanglizi/p/7523898.html