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

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. appium运行from appium import webdriver 提示most recent call last

    这是因为首次启动提示没有APPIUM 模块,CMD 执行 :pip3 install Appium-Python-Client

  2. ZOJ 3885 The Exchange of Items

    The Exchange of Items Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...

  3. volatile可见性和指令重排

    volatile关键字的2个作用 1.线程的可见性 2.防止指令重排 什么是线程的可见性? 线程的可见性 就是一个线程对一个变量进行更改操作 其他线程获取会获得最新的值. 线程在执行的行 操作主线程的 ...

  4. 洛谷——P2657 低头一族

    https://www.luogu.org/problem/show?pid=2657 题目描述 一群青年人排成一队,用手机互相聊天. 每个人的手机有一个信号接收指标,第i个人的接收指标设为v[i]. ...

  5. 移除apsx视图引擎,及View目录下的web.config的作用

    <> 使用Rezor视图引擎的时候移除apsx视图引擎 Global.asax文件 using System; using System.Collections.Generic; usin ...

  6. 《学习opencv》笔记——基本数据结构,CvMat,矩阵訪问

        老板让让做一个东东.输入端要用到opencv顺便就来学习一下.买了本书<学习opencv>翻来一看,opencv1.0,去官网上一看.opencv2.49,瞬间有种蛋碎的赶脚.看着 ...

  7. 2016.02.23,英语,《Vocabulary Builder》Unit 01

    Bell:来源于拉丁语,含义为war.fight,其中Bellona [bә'lәunә]是罗马女战神的名字,她的丈夫是战神Mars.antebellum: [ˌænti'beləm] adj. 战前 ...

  8. hdoj--3440--House Man(差分约束)

    House Man Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  9. Linux 下 新增Oracle10g 实例

    主要分为5步:创建实例目录,创建密码文件,创建参数文件,创建建库脚本并建库,创建数据字典. 其中,需要特别注意2点: 目录的权限,即用户和所属用户组都要是oracle.可以切换到已存在的oracle用 ...

  10. 2.Matlab数值数组及其运算

    2.1引导 2.2一维数组的创建与寻访 2.3二维数组的创建 2.4二维数组元素的标识 2.5二维数组的子数组寻访和赋值 2.6执行数组运算的常用函数 2.7数组运算和矩阵运算 2.8多项式的表达和创 ...