这道题想了很久不知道怎么设置状态,怎么拓展,怎么判重, 最后看了这哥们的博客 终于明白了。

https://blog.csdn.net/u014800748/article/details/47400557

这道题的难点在于怎么设置联通的状态,以及怎么拓展判重 .

(1)状态:这里状态先定义了一个格子cell, 有x和y坐标。然后set<cell>表示一个联通块, 再用set<set<cell>>表示n个连块可以组成的所有联通块, 这里是集合套集合。

(2)拓展:每个格子向四个方向拓展。平移方面用到了标准化,感性的认识就是把这个图形整个移到了左下角(具体看代码), 然后旋转,这里有一个规律,就是所有的格子都是 (x, y) -> (y, -x) ,每次执行都会旋转90度,记得最后返回的是标准化后的图形。翻转的话,沿x轴翻转, 即(x, y)-> (x, -y), 然后再旋转四次,其中旋转180度后即是y轴翻转的结果,已经包含在里面了,所以不用另外写。

(3)最后就是打表,在多组数据而每组数据程序运行的时候会做重复的事情的时候,用打表会比直接做更快一些

代码如下

#include<cstdio>
#include<algorithm>
#include<set>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std; struct cell
{
int x, y;
cell(int x = 0, int y = 0) : x(x), y(y) {}
bool operator < (const cell& rhs) const
{
return x < rhs.x || (x == rhs.x && y < rhs.y); //固定写法
}
}; const int MAXN = 11;
typedef set<cell> piece;
int ans[MAXN][MAXN][MAXN];
set<piece> poly[MAXN];
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0}; inline piece normalize(piece p0)
{
int minx = 15, miny = 15; //最大也就10,这里表示最大值
for(auto& t : p0)
{
minx = min(minx, t.x);
miny = min(miny, t.y);
}
piece ret;
for(auto& t : p0) ret.insert(cell(t.x - minx, t.y - miny)); //这种遍历方式要c++11, 编译选项要加入-std=c++11
return ret;
} inline piece rotate(piece p0)
{
piece ret;
for(auto& t : p0) ret.insert(cell(t.y, -t.x));
return normalize(ret);
} inline piece file(piece p0)
{
piece ret;
for(auto& t : p0) ret.insert(cell(t.x, -t.y));
return normalize(ret);
} void add(piece p0, cell c)
{
piece p = p0;
p.insert(c);
p = normalize(p); int id = p.size();
REP(i, 0, 4)
{
if(poly[id].count(p)) return;
p = rotate(p);
}
p = file(p);
REP(i, 0, 4)
{
if(poly[id].count(p)) return;
p = rotate(p);
} poly[id].insert(p);
} void work()
{
piece start;
start.insert(cell(0, 0));
poly[1].insert(start); REP(n, 2, MAXN)
for(auto& p : poly[n-1]) // 这里n-1,因为是从前一个拓展过来的
for(auto& t : p)
REP(i, 0, 4)
{
cell temp(t.x + dir[i][0], t.y + dir[i][1]);
if(!p.count(temp)) add(p, temp);
} REP(n, 1, MAXN)
REP(w, 1, MAXN)
REP(h, 1, MAXN)
{
int cnt = 0;
for(auto& p : poly[n])
{
int maxx = 0, maxy = 0;
for(auto & t : p)
{
maxx = max(maxx, t.x);
maxy = max(maxy, t.y);
}
if(max(maxx, maxy) < max(w, h) && min(maxx, maxy) < min(w, h)) cnt++; //是否符合题目要求
}
ans[n][w][h] = cnt;
}
} int main()
{
work();
int n, w, h;
while(~scanf("%d%d%d", &n, &w, &h))
printf("%d\n", ans[n][w][h]); //提前打表
return 0;
}

紫书 例题7-14 UVa 1602(搜索+STL+打表)的更多相关文章

  1. 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)

    这道题写了两个多小时-- 首先讲一下怎么建模 我们的目的是让所有点的出度等于入度 那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度 那么显然, 按照书里的思路,将边方向后,就相当 ...

  2. 紫书 例题8-3 UVa 1152(中途相遇法)

    这道题要逆向思维, 就是求出答案的一部分, 然后反过去去寻找答案存不存在. 其实很多其他题都用了这道题目的方法, 自己以前都没有发现, 这道题专门考这个方法.这个方法可以没有一直往下求, 可以省去很多 ...

  3. 紫书 例题8-12 UVa 12627 (找规律 + 递归)

    紫书上有很明显的笔误, 公式写错了.g(k, i)的那个公式应该加上c(k-1)而不是c(k).如果加上c(k-1)那就是这一次 所有的红气球的数目, 肯定大于最下面i行的红气球数 我用的是f的公式, ...

  4. 紫书 例题8-4 UVa 11134(问题分解 + 贪心)

     这道题目可以把问题分解, 因为x坐标和y坐标的答案之间没有联系, 所以可以单独求两个坐标的答案 我一开始想的是按照左区间从小到大, 相同的时候从右区间从小到大排序, 然后WA 去uDebug找了数据 ...

  5. 紫书 例题8-17 UVa 1609 (构造法)(详细注释)

    这道题用构造法, 就是自己依据题目想出一种可以得到解的方法, 没有什么规律可言, 只能根据题目本身来思考. 这道题的构造法比较复杂, 不知道刘汝佳是怎么想出来的, 我想的话肯定想不到. 具体思路紫书上 ...

  6. 紫书 例题 9-5 UVa 12563 ( 01背包变形)

    总的来说就是价值为1,时间因物品而变,同时注意要刚好取到的01背包 (1)时间方面.按照题意,每首歌的时间最多为t + w - 1,这里要注意. 同时记得最后要加入时间为678的一首歌曲 (2)这里因 ...

  7. 紫书 例题 10-2 UVa 12169 (暴力枚举)

    就是暴力枚举a, b然后和题目给的数据比较就ok了. 刘汝佳这道题的讲解有点迷,书上讲有x1和a可以算出x2, 但是很明显x2 = (a * x1 +b) 没有b怎么算x2?然后我就思考了很久,最后去 ...

  8. 紫书 例题 10-12 UVa 1637(概率计算)

    以9元组来代表当前状态,每一元是每一堆剩下的牌数 枚举当前状态所有可以拿掉牌的情况,然后递归下去求 概率,当牌拿完的时候概率为1 那么这里的实现非常的秀,用到了vector来代表9元组 然后还用到了m ...

  9. 紫书 例题 10-26 UVa 11440(欧拉函数+数论)

    这里用到了一些数论知识 首先素因子都大于M等价与M! 互质 然后又因为当k与M!互质且k>M!时当且仅当k mod M! 与M!互质(欧几里得算法的原理) 又因为N>=M, 所以N!为M! ...

随机推荐

  1. iOS 打印出视图中全部的子视图的名称

    使用递归: - (void)listSubviewsOfView:(UIView *)view { // Get the subviews of the view NSArray *subviews ...

  2. [BZOJ 3884][欧拉定理]上帝与集合的正确使用方法

    看看我们机房某畸形写的题解:http://blog.csdn.net/sinat_27410769/article/details/46754209 此题为popoQQQ神犇所出,在此orz #inc ...

  3. 深入分析JavaWeb Item39 -- 监听器(Listener)学习进阶

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  4. BZOJ3170: [Tjoi2013]松鼠聚会

    [传送门:BZOJ3170] 简要题意: 给出n个点的坐标,规定两个点的距离=max(|x1-x2|,|y1-y2|) 要求选出一个点,使得这个点到所有点的距离和最小 题解: 切比雪夫转换例题 将一个 ...

  5. gemm() 与 gesvd() 到矩阵求逆(inverse)(根据 SVD 分解和矩阵乘法求矩阵的逆)

    可逆方阵 A 的逆记为,A−1,需满足 AA−1=I. 在 BLAS 的各种实现中,一般都不会直接给出 matrix inverse 的直接实现,其实矩阵(方阵)的逆是可以通过 gemm()和gesv ...

  6. Oracle 优化和性能调整

    分析评价Oracle数据库性能主要有数据库吞吐量.数据库用户响应时间两项指标.数据库用户响应时间又可以分为系统服务时间和用户等待时间两项,即:  数据库用户响应时间=系统服务时间+用户等待时间  因此 ...

  7. Visual Studio2013下Magick++配置方法

    声明:本文系作者原创,如需转载请保持文章完整并注明出处(http://blog.csdn.net/u010281174/article/details/52224829). ImageMagick是一 ...

  8. javascript前端如何使用google-protobuf

    1.首先下载google的protobuf的compiler,通过编译器可以将.proto文件转换为想要的语言文件. 下载地址:https://repo1.maven.org/maven2/com/g ...

  9. Spark RDD概念学习系列之Pair RDD的transformation操作

    不多说,直接上干货! Pair RDD的transformation操作 Pair RDD转换操作1 Pair RDD 可以使用所有标准RDD 上转化操作,还提供了特有的转换操作. Pair RDD转 ...

  10. SQL Server-聚焦使用索引和查询执行计划

    前言 上一篇我们讲了聚集索引对非聚集索引的影响,对数据库一直在强调的性能优化,所以这一节我们统筹讲讲利用索引来看看查询执行计划是怎样的,简短的内容,深入的理解,Always to review the ...