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", (n==1)?1:show(w, h));
100
101     return 0;
102 }

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

时间: 2024-08-06 01:35:19

UVA 1602 Lattice Animals解题思路(打表+set)的相关文章

UVA - 1602 Lattice Animals (暴力+同构判定)

题目链接 题意:求能放进w*h的网格中的不同的n连通块个数(通过平移/旋转/翻转后相同的算同一种),1<=n<=10,1<=w,h<=n. 刘汝佳的题真是一道比一道让人自闭...QAQ~~ 这道题没什么好的办法,Polya定理也毫无用武之地,只能暴力构造出所有可能的连通块,然后用set判重,比较考验基本功. 连通块可以用一个结构体D来表示,D的n代表黑块数量,然后有至多10个点P(x,y),用另一个结构体数组P[N]来表示. 问题的关键在于如何判重. 首先要知道set是通过<

【DFS】【打表】Lattice Animals

[ZOJ2669]Lattice Animals Time Limit: 5 Seconds      Memory Limit: 32768 KB 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 polyminoes. Polymino

uva 1549 - Lattice Point(暴力)

题目链接:uva 1549 - Lattice Point 题目大意:给定圆半径,以原点为圆心,求园内有多少个整数点. 解题思路:首先坐标轴将圆分成4份,所以只要单独考虑每一块的个数乘4再加1即可(原点) #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const double pi = 4 * atan(1.0);

LeetCode解题思路:595. Big Countries

There is a table World +-----------------+------------+------------+--------------+---------------+ | name | continent | area | population | gdp | +-----------------+------------+------------+--------------+---------------+ | Afghanistan | Asia | 652

UVA 11768 - Lattice Point or Not(数论)

UVA 11768 - Lattice Point or Not option=com_onlinejudge&Itemid=8&page=show_problem&category=516&problem=2868&mosmsg=Submission+received+with+ID+13823461" target="_blank" style="">题目链接 题意:给定两个点,构成一条线段.这些点都是十分

UVA - 10396 Vampire Numbers 暴力+打表

题目大意:给出n,要求你输出所有符合规则的n位数 规则如下,这个n位数由两个n/2位数相乘得到,并且满足 1.这n位数为偶数 2.这两个n/2位数上的所有数刚好组成了这n位数 3.两个n/2位数不能都是10的倍数 解题思路:因为输入只有4,6,8,所以先预处理,暴力枚举4,6,8的情况,然后打表 #include<cstdio> #include<set> #include<cmath> using namespace std; #define maxn 10 set&

MYSQL-----使用select查询,解题思路总结---精髓!

select查询语句,作为测试人员,使用此语句是家常便饭,是必须掌握的部分,由开始学习mysql到网上搜索试题做,开始做题一塌糊涂,拿到题目就晕,无从下手,现在慢慢总结了一套自己做题的方式,很开森,嘿嘿!由简单试题到较难试题的解答,思路其实都是一样的,今天将做题思路进行总结,(说明:用到的关键字等自行学习,只讲解题思路)详见如下: 我们在查询时会用到的表,有4张表格如下: 1.查询出'计算机系'教师所教课程的成绩表 解题思路: 1.1)首先根据题目要求,找到相关连表,此处涉及到的表为:教师表.课

UVA 1482 - Playing With Stones(SG打表规律)

UVA 1482 - Playing With Stones 题目链接 题意:给定n堆石头,每次选一堆取至少一个,不超过一半的石子,最后不能取的输,问是否先手必胜 思路:数值很大,无法直接递推sg函数,打出前30项的sg函数找规律 代码: #include <stdio.h> #include <string.h> int t, n; long long num; long long SG(long long x) { return x % 2 == 0 ? x : SG(x /

&quot;巴卡斯杯&quot; 中国大学生程序设计竞赛 - 女生专场(重现)解题思路

此文章可以使用目录功能哟↑(点击上方[+]) 经过这么一次女生赛,告诉我们千万不要小瞧女生,不然会死得很惨,orz... 链接→"巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场(重现)  Problem 1001 Solving Order Accept: 0    Submit: 0 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit : 32768/32768 K (Java/Others)  Problem Descri