题目链接 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了就交上来。: )

转载于:https://www.cnblogs.com/tanglizi/p/7523898.html

UVA-1602 Lattice Animals 搜索问题(打表+set)相关推荐

  1. UVA 1602 Lattice Animals

    https://vjudge.net/problem/UVA-1602 题意:w*h网格里放n连块,问有多少种放法 翻转.旋转90°.平移之后相同的算一种 推荐题解: http://blog.csdn ...

  2. UVa 1602:Lattice Animals(BFS)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=841& ...

  3. UVA1602 Lattice Animals 网格动物

    题目:输入n,w,h(1n10,1w,hn),求能放在w*h网格里的不同的n连块的个数(注意:平移.旋转.翻转后相同的算作同一种). 分析:本题关键就是如何判重,有n个格子连通,所幸n很小,可以回溯求 ...

  4. uva 11174(排列组合+搜索)

    依然是liurujia计数练习题.依然是自己想没想出来,在MOD是素数的情况下除以x即为乘x的逆.这个真心以前没听过,用了这个方法后处理就变得十分巧妙. 整个程序步骤还是很清晰的,先上来算阶乘与逆(求 ...

  5. UVA 10158 (记忆化搜索)

    题目大意: 已知有n个人,他们之间有敌对还有友好关系,已知: 自己和自己为好友. a和b为好友,那么b和a也为好友 自己的敌人是敌人. 自己和自己不能为敌人. a和b为敌人,那么b和a也为敌人 敌人的 ...

  6. EXCEL函数运用【关键词搜索另一个表的内容】【二个单元格是否一致】

    如下图,如果你想查香蕉的销量那怎么办? 比对的如果是数字,那要确认二组内空是不是数字格式,我被坑过,数字去匹配文本无效,文章末尾有如果批量[转换为数字]. 如果在另一个表,参考这一段 =IFERROR ...

  7. 图的深度优先搜索和广度优先搜索(邻接表) - Java实现

    文章目录 前言 1.什么是图? 2.图如何表示? 3.如何创建一个邻接表 一.深度优先搜索(Depth First Search) 二.广度优先搜索(Breadth First Search) 三.寻 ...

  8. 【PAT】PAT总结《搜索、打表、分治、排序算法、队列、栈、堆、Hash》

    打表 打表这个技巧其实我们在素数部分的题已经涉及到了.还是要仔细思考,什么时候应该打表,打表有助于减少后续的计算的时候,我们应该打表, 特别是查询量特别大,即时计算无论多么快都会超时的情况.或者逆向运 ...

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

    UVA 1482 - Playing With Stones 题目链接 题意:给定n堆石头,每次选一堆取至少一个.不超过一半的石子,最后不能取的输,问是否先手必胜 思路:数值非常大.无法直接递推sg函 ...

最新文章

  1. dd指令打包iso文件 linux_从零开始学Linux运维|33.文件的打包压缩和解压
  2. opc客户端_组态王作为OPC服务器的使用介绍,欢迎读者阅读
  3. 浅谈Python http库 httplib2
  4. flask那啥 pycharm专业版提供的模板
  5. 深度学习stride_深度学习圣经“花书”各章摘要与笔记整理
  6. 视频搜索时代到来了吗?[翻译]
  7. 集成学习——机器学习(周志华)
  8. 快递鸟接口国内常用快递公司编码表
  9. Java根据位置获取经纬度计算距离
  10. java 堆栈的声明_Java 堆栈
  11. 分享几个实用的破解软件
  12. 【QT】缺少Qt5Widgetsd.dll等文件的问题
  13. defineEmit
  14. 利用phantomjs动态生成图片
  15. 4个终于被破解的世界密码
  16. TI官方代码中的任务状态机
  17. [提升] 程序员的四境界、七宗罪与七武器
  18. android webview全屏显示html内容
  19. 推荐黑莓实用软件 bbChecklist [下]
  20. 语音信号处理 (speech signal processing) - 参考文献

热门文章

  1. linux 设置时钟 教程,Linux hwclock命令参数及用法详解--Linux显示/设置硬件时钟命令...
  2. 理解主从设备模式(Master-Slave)
  3. 剑指offer面试题[59]-对称的二叉树
  4. 从事测试的第6年 , 开工第二天五千字总结..我不平凡的2021
  5. 朋友圈如何测试(思维导图)
  6. a点到b点最短路线有多少条_8下数学培优:几何体上最短路径问题,总结与提升,不一样的感受...
  7. Golang入门~搭建Beego
  8. matlab虚拟现实之在V-Realm Builder2中建立父子关系
  9. python交互式方式、代码文件方式_涨见识了,在终端执行 Python 代码的 6 种方式
  10. python爬取热门新闻每日排行_用python查看百度搜索中今日热点事件排行榜