https://vjudge.net/problem/UVA-1602

题意:计算n连通块不同形态的个数。

思路:

实在是不知道该怎么做好,感觉判重实在是太麻烦了。

判重就是判断所有格子位置是否都相同,这样我们可以定义一个结构体来保存每个格子的坐标点,用set容器poly来保存这些格子,然后再用一个set容器poly_set来保存指定数量i个连通块的各个图形的坐标点,也就是说该容器是用来保存poly的。(不太好解释,具体可以看代码。)因为图形必须是连通的,所以在添加第i个格子的时候必定是在i-1个格子的基础上添加的。这样我们在添加第i个格子的时候,只需要遍历保存第(i-1)个连通块的poly_set,然后遍历它当中的每个格子,每个格子可以往4个方向发展。然后进行判断。

因为一个连通块可以在不同的坐标点,即使他们形状相同,也许坐标是不同的。所以首先需要将它们标准化,也就是平移。平移就是选取连通块中最小的x和y值,并将(x,y)定为(0,0)原点,这样每个图形就可以比较坐标了。当然,判重时还需要进行旋转,180度翻转操作,旋转的话就是每个格子都顺时针旋转90度即可。相应的几何变换为(x,y)->(y,-x)。180度翻转得几何变化就是(x,y)->(x,-y)。旋转和翻转后需要重新平移来标准化。

由于这道题数据不大,可以直接打表,这样数据多的时候比较快。

这道题目确实很不错,不过真的是挺麻烦的,借鉴了大神们的代码之后,看了很久终于理解了做法。

 #include<iostream>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std; const int dx[] = { -, , , };
const int dy[] = { , , -, };
const int N = ;
int n, w, h;
int ans[][][]; //打表之后的答案 struct Cell //定义单元格
{
int x, y;
Cell(int a, int b) { x = a; y = b; }
Cell() {}
bool operator < (const Cell&rhs) const //重载小于号,在set容器中排序
{
return x < rhs.x || (x == rhs.x && y < rhs.y);
}
}; typedef set<Cell>poly; //坐标的集合,也就是一个连通块(1,2,3....)
set<poly> poly_set[]; //有i个Cell的poly集合 //规范化到最小点(0,0)
poly normalize(poly& p)
{
poly this_p;
int min_x = p.begin()->x, min_y = p.begin()->y;
//找到最小的x和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;
} //向右翻转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)); //x值为原来的y值,y值为原来的-x值
}
//旋转之后需要将它规范化
return normalize(this_p);
} //向下翻转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)); //x坐标不变,y变号
}
return normalize(this_p);
} void check(const poly& this_p, Cell& this_c)
{
poly p = this_p;
p.insert(this_c); //标准化
p = normalize(p);
int n = p.size(); for (int i = ; i < ; i++)
{
//if (poly_set[n].find(p) != 0 )
if (poly_set[n].find(p) != poly_set[n].end()) //已存在
return;
//对该连通块向右旋转90度
p = rotate(p);
}
//将该连通块翻转180度
p = flip(p);
for (int i = ; i < ; i++)
{
if (poly_set[n].find(p) != poly_set[n].end())
return;
p = rotate(p);
}
//如果未重复则加入该连通块的集合
poly_set[n].insert(p);
} void Generate() //打表
{
//先生成一个连通块
poly s;
s.insert(Cell(, ));
poly_set[].insert(s); //插入到一个Cell的poly集合,只有一个格子的连通块只有这么一个
//根据有i-1个Cell(格子)的poly(连通块)集合来生成有i个Cell的poly集合
for (int i = ; i <= N; i++) //从生成第2个格子开始,一直到第10个
{
//遍历有i-1个Cell的连通块集合
for (set<poly>::iterator p = poly_set[i - ].begin(); p != poly_set[i - ].end(); p++)
{
//在每个连通块中遍历每个Cell即格子
for (poly::const_iterator q = p->begin(); q != p->end(); q++)
{
for (int j = ; j < ; j++)
{
Cell new_c(q->x + dx[j], q->y + dy[j]); //生成新格子
if (p->find(new_c) == p->end()) //如果在该坐标上还没有Cell(格子),则继续往下判断
{
check(*p, new_c); //判断当前连通块加上这个Cell坐标后是否存在
}
}
}
}
} //生成答案
for(int i = ; i <= N;i++)
{
for (int w = ; w <= i; w++)
{
for (int h = ; h <= i; h++)
{
int cnt = ;
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)) //判断能够放入网格的条件
cnt++; }
ans[i][w][h] = cnt;
}
}
}
} int main()
{
//freopen("D:\\txt.txt", "r", stdin);
Generate(); //打表
while (cin >> n >> w >> h)
{
cout << ans[n][w][h] << endl;
}
return ;
}

UVa 1602 网格动物(回溯)的更多相关文章

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

    题目链接 题意:求能放进w*h的网格中的不同的n连通块个数(通过平移/旋转/翻转后相同的算同一种),1<=n<=10,1<=w,h<=n. 刘汝佳的题真是一道比一道让人自闭.. ...

  2. ACM题目————网格动物

    Lattice animal is a set of connected sites on a lattice. Lattice animals on a square lattice are esp ...

  3. UVA 1602 Lattice Animals

    题目 输入n.w.h($1\leqslant n \leqslant 10, 1\leqslant w,h \leqslant n$),求能放在w*h网格里的不同的n连块的个数(注意,平移.旋转.翻转 ...

  4. UVa 208 Firetruck【回溯】

    题意:给出一个n个节点的无向图,以及某个节点k,按照字典序从小到大输出从节点1到节点k的所有路径 看的题解 http://blog.csdn.net/hcbbt/article/details/975 ...

  5. 网格动物UVA1602

    题目大意 输入n,w,h(1<=n<=10,1<=w,h<=n).求能放在w*h网格里的不同的n连块的个数(平移,旋转,翻转算一种) 首先,方法上有两个,一是打表,dfs构造连 ...

  6. Chinese Mahjong UVA - 11210 (暴力+回溯递归)

    思路:得到输入得到mj[]的各个牌的数量,还差最后一张牌.直接暴力枚举34张牌就可以了. 当假设得到最后一张牌,则得到了的牌看看是不是可以胡,如果可以胡的话,就假设正确.否者假设下一张牌. 关键还是如 ...

  7. UVA1602 Lattice Animals 网格动物 (暴力,STL)

    多联骨牌的生成办法,维基上只找到固定的骨牌fix,而free的没有找到. 于是只好写个set判重的简单枚举了. 旋转的操作,可以在坐标轴上画个点,以原点为轴心,逆时针旋转90度,新的点的坐标为(-y, ...

  8. 紫书 例题7-14 UVa 1602(搜索+STL+打表)

    这道题想了很久不知道怎么设置状态,怎么拓展,怎么判重, 最后看了这哥们的博客 终于明白了. https://blog.csdn.net/u014800748/article/details/47400 ...

  9. UVa 1602 Lattice Animals (STL && 生成n连块 && 无方向形状判重)

    题意 : 给定一个 w * h 的 矩阵,在矩阵中找不同n个连通块的个数(旋转,翻转,平移算作一种) 分析 : 这题的关键点有两个 ① 生成n连块并且存储起来(因为题目是多测试用例,如果每一次都重新生 ...

随机推荐

  1. mysql 数据库数据订正

    mysql 数据库数据订正 http://blog.itpub.net/22664653/viewspace-717175/ 工作过程中时常遇到数据订正的需求,该操作本身不难.操作时要求能够保持回滚~ ...

  2. Win10+vs2012+cuda8.0的安装与配置

    安装环境说明:NVDIA GeForce 930M.Intel(R) HD Graphics 520 显卡和cuda需要兼容匹配,我一开始下载的cuda6.5无法安装,所以又重新下了比较新的cuda8 ...

  3. [vue]vue v-on事件绑定(原生修饰符+vue自带事件修饰符)

    preventDefault阻止默认行为和stopPropagation终止传递 event.preventDefault() 链接本来点了可以跳转, 如果注册preventDefault事件,则点了 ...

  4. [py]面向对象图解assignment

    python的chained assignment 在python中 a is b is c 等价于 a is b and b is c 所以,猜猜 False is False is False # ...

  5. Java多线程的下载器(1)

    实现了一个基于Java多线程的下载器,可提供的功能有: 1. 对文件使用多线程下载,并显示每时刻的下载速度. 2. 对多个下载进行管理,包括线程调度,内存管理等. 一:单个文件下载的管理 1. 单文件 ...

  6. Java调用本地命令

    参考:http://blog.csdn.net/zhu_xun/article/details/19539513 http://www.cnblogs.com/kingcucumber/p/31801 ...

  7. Selenium Webdriver——操作隐藏的元素(二)display属性

    有时候我们会碰到一些元素不可见,这个时候selenium就无法对这些元素进行操作了.例如,下面的情况: 页面主要通过“display:none”来控制整个下拉框不可见.这个时候如果直接操作这个下拉框, ...

  8. Perl的debug小技巧

    进入Perl的调试环境的命令:  Perl  -d  perl_file 设置断点:b + perl代码中的行号. 执行到断点:c 表示continue until breakpoint. 执行下一条 ...

  9. python爬虫对于gb2312

    对于刚刚接触python爬虫的人,常常会碰到一个比较烦的问题, 如果网页是GB2312编码格式,我们直接decode(’GB2312‘)一般python都会报错: GB2312不能编码该页面. 这就比 ...

  10. 解决nginx下不能require根目录以外的文件

    我们常规的做法是将统一入口文件.css.js这些放在网站根木,其他php文件放到根目录外部,这个时候nginx访问是require不到的,需要设定一下 1.vi  /usr/local/nginx/c ...