3.棋盘迷宫
(boardgame.pas/c/cpp)
(boardgame.in/out)
时间限制:5s/空间限制:256M
【题目描述】
小 A 和小 Z 是非常要好的朋友, 而且他们都对迷宫游戏非常有兴趣。 他们经
常在自习课上用迷宫来打发时间(两位都是学习效率 400%的 dalao, 大家切记不
要模仿) 。
他们的迷宫非常简单, 又被他们叫做是棋盘迷宫, 迷宫本身是一个 N*M 大小
的棋盘, 从左往右列数不断加大, 从上往下行数不断增大, 故左上角的坐标为(1,
1),右下角的坐标为(N,M) 。 当你处在坐标为(X,Y) 的格子里时, 你只能走到
(X+1,Y) 或(X,Y+1) , 即只能往右走或者往下走(当然你也不能走出棋盘) 。
同时部分格子中有障碍物, 这样的格子是不能经过的, 用‘#’ 代表, 能正常通
行的格子由‘.’ 代表。
每一轮游戏先由其中一人选定起点和终点, 由另外一个人来完成) 。 但是他
们很快发现, 并不是每次都能找到一条从起点到达终点的路径, 两位 dalao 的注
意力立刻从游戏转移到了如何快速判断路径是否存在这个问题上。
当然 dalao 们瞬间得到了算法, 不过他想考考你, 如果你能顺利解决, 也许
就能得到他们两个的签名哦! (据说是最高级别的因果律护身符, 能让人逢考必
过)
【输入格式】 (boardgame.in)
一共 N  Q  2 行。
第一行两个正整数为 N, M , 表示棋盘迷宫的行列。
接下来 N 行, 每行一个长度为 M 的字符串, 由‘#’ ‘.’ 两种字符组成
接下来 1 行, 一个正整数 Q ,表示询问的个数
接下来 Q 行, 每行四个正整数 x1,y1,x2,y2 询问点(x1,y1) 到(x2,y2) 是
否有一条合法的路径
数据保证(x1,y1) (x2,y2) 所在的位置都是‘.’ , 同时 x1<=x2,y1<=y2
【输出格式】 (boardgame.out)
一共 Q 行, 每行一个字符串Yes 或者 No , 对应每一个询问的答案。

分析:思路比较新奇的一道题。在线做是做不到满分的,只有离线了看看多组询问有什么特征.如果询问点对一个点在图的上半部分,一个点在图的下半部分,那么它们之间的路径肯定要经过中间.考虑一个类似meet in the middle的思想,我们从中间那条线上的点分别向上和向下延伸,看看它能到达哪些点,这样就能处理点对上的点分布在上下两个半图的情况,如果不在同一半图怎么办呢?分治递归就可以了.因为最后点对的两个点肯定要经过中间这条线上的同一个点,所以我们记录f[i][j][k]来表示(i,j)能够到达中间线上的哪些点(k是状态),最后利用二进制处理一下就好了.标程用了bitset,学了一下,似乎挺好用的.

超多组询问问题我人为要么就是预处理一下,要么就是询问之间肯定有公共类似的部分,从这个公共部分出发,就能通过枚举少数解得到多数解.

#include <cstdio>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; int n, m, q, flag[];
char s[][];
bitset <> f[][], g[][]; struct node
{
int x1, y1, x2, y2, id;
}; void dfs(vector <node> v, int l, int r)
{
if (l > r)
return;
int mid = (l + r) >> ;
for (int i = mid; i >= l; i--) //从合法状态扩展到合法状态,必须倒着枚举
for (int j = m; j >= ; j--)
{
f[i][j] = ;
if (s[i][j] == '.')
{
if (i == mid)
f[i][j].set(j);
else
f[i][j] |= f[i + ][j];
if (j != m)
f[i][j] |= f[i][j + ];
}
}
for (int i = mid; i <= r; i++)
for (int j = ; j <= m; j++)
{
g[i][j] = ;
if (s[i][j] == '.')
{
if (i == mid)
g[i][j].set(j);
else
g[i][j] |= g[i - ][j];
if (j != )
g[i][j] |= g[i][j - ];
}
}
vector <node> vl, vr;
for (vector <node>::iterator it = v.begin(); it != v.end(); it++)
{
node q = *it;
if (q.x2 < mid)
vl.push_back(q);
else
if (q.x1 > mid)
vr.push_back(q);
else
flag[q.id] = (f[q.x1][q.y1] & g[q.x2][q.y2]).any();
}
dfs(vl, l, mid - );
dfs(vr, mid + , r);
} int main()
{
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++)
scanf("%s", s[i] + );
vector <node> v;
scanf("%d", &q);
for (int i = ; i <= q; i++)
{
node temp;
scanf("%d%d%d%d", &temp.x1, &temp.y1, &temp.x2, &temp.y2);
temp.id = i;
v.push_back(temp);
}
dfs(v, , n);
for (int i = ; i <= q; i++)
{
if (flag[i])
printf("Yes\n");
else
printf("No\n");
} return ;
}

清北学堂模拟赛d6t6 棋盘迷宫的更多相关文章

  1. 清北学堂模拟赛day7 数字碰撞

    /* clj:水题别人都满分你不是你就完了,所以说水题一定要细心一点,有这么几个细节:①前导零的处理,全是零的时候要特判②换行要注意,不要多大一行,剩下就是水水的模拟了 */ #include< ...

  2. 清北学堂模拟赛d4t1 a

    分析:大模拟,没什么好说的.我在考场上犯了一个超级低级的错误:while (scanf("%s",s + 1)),导致了死循环,血的教训啊,以后要记住了. /* 1.没有发生改变, ...

  3. 清北学堂模拟赛day7 错排问题

    /* 考虑一下已经放回m本书的情况,已经有书的格子不要管他,考虑没有书的格子,不考虑错排有(n-m)!种,在逐步考虑有放回原来位置的情况,已经放出去和已经被占好的格子,不用考虑,剩下全都考虑,设t=x ...

  4. 清北学堂模拟赛day7 石子合并加强版

    /* 注意到合并三堆需要枚举两个端点,其实可以开一个数组记录合并两堆的结果,标程好像用了一个神奇的优化 */ #include<iostream> #include<cstdio&g ...

  5. 清北学堂模拟赛d1t2 火柴棒 (stick)

    题目描述众所周知的是,火柴棒可以拼成各种各样的数字.具体可以看下图: 通过2根火柴棒可以拼出数字“1”,通过5根火柴棒可以拼出数字“2”,以此类推. 现在LYK拥有k根火柴棒,它想将这k根火柴棒恰好用 ...

  6. 清北学堂模拟赛d1t1 位运算1(bit)

    题目描述LYK拥有一个十进制的数N.它赋予了N一个新的意义:将N每一位都拆开来后再加起来就是N所拥有的价值.例如数字123拥有6的价值,数字999拥有27的价值.假设数字N的价值是K,LYK想找到一个 ...

  7. 清北学堂模拟赛d2t6 分糖果(candy)

    题目描述总共有n颗糖果,有3个小朋友分别叫做L,Y,K.每个小朋友想拿到至少k颗糖果,但这三个小朋友有一个共同的特点:对3反感.也就是说,如果某个小朋友拿到3颗,13颗,31颗,333颗这样数量的糖果 ...

  8. 清北学堂模拟赛d2t5 吃东西(eat)

    题目描述一个神秘的村庄里有4家美食店.这四家店分别有A,B,C,D种不同的美食.LYK想在每一家店都吃其中一种美食.每种美食需要吃的时间可能是不一样的.现在给定第1家店A种不同的美食所需要吃的时间a1 ...

  9. 清北学堂模拟赛d2t4 最大值(max)

    题目描述LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目:这里有一个长度为n的正整数数列ai(下标为1~n).并且有一个参数k.你需要找两个正整数x,y,使得x+k<=y, ...

随机推荐

  1. [Clr via C#读书笔记]Cp11事件

    Cp11事件 类型之所以提供事件通知功能,是因为类型维护了一个已登记方法的列表,事件发生后,类型将通知列表登记的所有方法: 事件模型建立在委托的基础上.委托是调用回调方法的一种类型安全的方式. 设计事 ...

  2. cenos环境变量配置

    Beego环境搭建和bee工具安装使用,以Windows环境为例. 首先,下载并安装好GO并配置好GOROOT和GOPATH环境变量(如果您是用msi包安装的go,那么这些环境变量已经设置好了).并在 ...

  3. BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集

    题目链接:http://uoj.ac/problem/274 题意概述: 没什么好概述的......概述了题意就知道怎么做了......我懒嘛 分析: 就是用lct维护最大生成树. 然后如果去UOJ上 ...

  4. Python中的名字隐藏

    Python对于module文件中的name是没有private和public区分的,严格来说,在module文件重定义的任何name,都可以被外界访问.但是,对于 from module imort ...

  5. Beta阶段项目展示博客

    Beta阶段项目展示 团队成员的简介 详细见团队简介 角色 姓名 照片 项目经理,策划 游心 策划 王子铭 策划 蔡帜 美工 赵晓宇 美工 王辰昱 开发.架构师 解小锐 开发 陈鑫 开发 李金奇 开发 ...

  6. Android开发随笔5

    昨天: 对界面的进一步设计补充 可以在界面之间的跳转 研究了对图标等的操作 今天: 实现对库的相关操作 学习视视频内容‘ 复习java的一些知识.

  7. Python 服务器端表单验证插件

    Python格式验证库 Cerberus 作者 MrStranger 关注 2016.08.02 14:44 字数 2140 阅读 79评论 0喜欢 1 Cerberus是一个验证Python对象.M ...

  8. object-oriented 第二次作业(2)

    面向对象程序设计自学计划 由于我的英文实在是很差,所以我就没有去考虑看英文的课程视频.网络上的课程有很多,什么学校的也有,一开始我不知道该如何开始选择课程.感觉每个都还可以.后来在群里的看到别人推荐的 ...

  9. lintcode-189-丢失的第一个正整数

    189-丢失的第一个正整数 给出一个无序的正数数组,找出其中没有出现的最小正整数. 样例 如果给出 [1,2,0], return 3 如果给出 [3,4,-1,1], return 2 挑战 只允许 ...

  10. C# HttpWebRequest post提交数据,提交对象

    1.客户端方法 //属于客户端 //要向URL Post的方法 public void PostResponse() { HttpWebRequest req = (HttpWebRequest)Ht ...