bzoj5138 [Usaco2017 Dec]Push a Box
题目描述:
题解:
暴力可以记录$AB$位置转移,这个时候状态是$n^4$的,无法接受。
考虑只记录$A$在$B$旁边时的状态,这个时候状态时$n^2$的。
所以说转移有两种,一种是$A$推$B$一下,另一种是$A$绕到$B$另一侧。
第一种转移显然$O(1)$,瓶颈在第二种。
发现这对点满足点双,所以建出广义圆方树,判两个点是否同父亲或一个点是另一个点的爷爷。
时间复杂度$O(n^2)$。
代码:
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = ;
template<typename T>
inline void read(T&x)
{
T f = ,c = ;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){c=c*+ch-'';ch=getchar();}
x = f*c;
}
int n,m,Q,nam[N][N],tot,rtx,rty,rt,stx,sty,st,hed[N*N],cnt=;
char mp[N][N];
bool check(int x,int y){return x&&y&&x<=n&&y<=m;}
int dx[]={-,,,},dy[]={,,-,};
struct EG
{
int to,nxt;
}e[*N*N];
void ae(int f,int t)
{
e[++cnt].to = t;
e[cnt].nxt = hed[f];
hed[f] = cnt;
}
int dfn[N*N],low[N*N],tim,fa[N*N*];
int sta[N*N*],tl;
void tarjan(int u,int f)
{
dfn[u] = low[u] = ++tim;
sta[++tl] = u;
for(int j=hed[u];j;j=e[j].nxt)
{
int to = e[j].to;
if(to==f)continue;
if(!dfn[to])
{
tarjan(to,u);
low[u] = min(low[u],low[to]);
if(low[to]>=dfn[u])
{
int now = ++tot;
fa[now] = u;
int c = -;
while(c!=to)
{
c = sta[tl--];
fa[c] = now;
}
}
}else low[u] = min(low[u],dfn[to]);
}
}
bool ck(int u,int v)
{
if(fa[u]==fa[v])return ;
if(fa[fa[v]]==u)return ;
if(fa[fa[u]]==v)return ;
return ;
}
bool dp[N][N][];
bool vis[N][N];
struct Pair
{
int x,y;
Pair(){}
Pair(int x,int y):x(x),y(y){}
};
void bfs()
{
queue<Pair>q;
q.push(Pair(rtx,rty));
vis[rtx][rty] = ;
while(!q.empty())
{
Pair tp = q.front();q.pop();
int x = tp.x,y = tp.y;
for(int k=;k<;k++)
{
int xx = x+dx[k],yy = y+dy[k];
if(!nam[xx][yy])continue;
if(xx==stx&&yy==sty)dp[stx][sty][k]=;
else if(!vis[xx][yy])vis[xx][yy]=,q.push(Pair(xx,yy));
}
}
}
struct Tri
{
int x,y,z;
Tri(){}
Tri(int x,int y,int z):x(x),y(y),z(z){}
};
void sol()
{
queue<Tri>q;
for(int k=;k<;k++)if(dp[stx][sty][k])
q.push(Tri(stx,sty,k));
while(!q.empty())
{
Tri tp = q.front();
q.pop();
int x = tp.x,y = tp.y,k = tp.z;
if(nam[x+dx[k]][y+dy[k]]&&!dp[x+dx[k]][y+dy[k]][k])dp[x+dx[k]][y+dy[k]][k]=,q.push(Tri(x+dx[k],y+dy[k],k));
for(int i=;i<;i++)if(nam[x-dx[i]][y-dy[i]]&&i!=k&&ck(nam[x-dx[k]][y-dy[k]],nam[x-dx[i]][y-dy[i]])&&!dp[x][y][i])
dp[x][y][i]=,q.push(Tri(x,y,i));
}
}
bool cck(int x,int y){return dp[x][y][]||dp[x][y][]||dp[x][y][]||dp[x][y][]||(x==stx&&y==sty);}
int main()
{
// freopen("tt.in","r",stdin);
read(n),read(m),read(Q);
for(int i=;i<=n;i++)
{
scanf("%s",mp[i]+);
for(int j=;j<=m;j++)if(mp[i][j]!='#')
{
nam[i][j] = ++tot;
if(mp[i][j]=='A')rt=tot,rtx=i,rty=j;
if(mp[i][j]=='B')st=tot,stx=i,sty=j;
}
}
for(int i=;i<=n;i++)for(int j=;j<=m;j++)if(mp[i][j]!='#')
{
int u = nam[i][j];
for(int x,y,k=;k<;k++)
{
x = i+dx[k],y = j+dy[k];
if(!check(x,y)||mp[x][y]=='#')continue;
ae(u,nam[x][y]);
}
}
tarjan(rt,);
bfs();sol();
for(int x,y,i=;i<=Q;i++)
{
read(x),read(y);
puts(cck(x,y)?"YES":"NO");
}
return ;
}
bzoj5138 [Usaco2017 Dec]Push a Box的更多相关文章
- 【BZOJ5138】[Usaco2017 Dec]Push a Box(强连通分量)
[BZOJ5138][Usaco2017 Dec]Push a Box(强连通分量) 题面 BZOJ 洛谷 题解 这题是今天看到萝卜在做然后他一眼秒了,我太菜了不会做,所以就来做做. 首先看完题目,是 ...
- BZOJ5142: [Usaco2017 Dec]Haybale Feast(双指针&set)(可线段树优化)
5142: [Usaco2017 Dec]Haybale Feast Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 182 Solved: 131[ ...
- luogu P4082 [USACO17DEC]Push a Box
传送门 一个人推箱子,和之前的华容道中的棋子移动有异曲同工之妙,因为每次可以让人走到箱子的其他方向上,或者推一下箱子 所以状态可以设成\(f_{i,j,k}\),即箱子在\((i,j)\),人在\(k ...
- [Usaco2017 Dec] A Pie for a Pie
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=5140 [算法] 最短路 时间复杂度 : O(N^2) [代码] #include&l ...
- [USACO17DEC]Push a Box
https://www.zybuluo.com/ysner/note/1293166 题面 戳我 解析 挺不错的一道图论码量题. 可以借此回顾一下\(noip2013\)华容道. 思路和华容道差不多. ...
- Luogu P4082 [USACO17DEC]Push a Box 点双连通分量/圆方树
(貌似有圆方树的做法,我写的是点双) 显然这道题就是直接搜索.定义状态为f[i][j][0~4]表示箱子在(i,j),人在某个方向推.然后问题就是怎么转向.我们发现如果要转向,必须是人走过一条不包括( ...
- BZOJ5142: [Usaco2017 Dec]Haybale Feast 线段树或二分答案
Description Farmer John is preparing a delicious meal for his cows! In his barn, he has NN haybales ...
- [BZOJ5139][Usaco2017 Dec]Greedy Gift Takers 权值线段树
Description Farmer John's nemesis, Farmer Nhoj, has NN cows (1≤N≤10^5), conveniently numbered 1…N. T ...
- BZOJ5137[Usaco2017 Dec]Standing Out from the Herd
看了半天题 不知道怎么用SAM维护 于是借(chao)鉴(xi)的一发神犇的 只要判断这个子串之前被标记的记号(也就是他属于第几个串)和这次转移到的是否相同 如果不同就说明该子串属于多个串 直接标记- ...
随机推荐
- 2018全球十大测试工具Top2 Katalon
引言 由Capgemini,Sogeti和Micro Focus发布的2017-2018年世界质量报告中,Katalon超越老牌测试工具UFT(源自QTP)成为黑马新秀,在全球十大自动化测试工具中排名 ...
- JAVA团队开发手册 - 3. 开发流程
开发流程 对于一个项目,最大的问题就是如何拆解为任务,分配到合适的人手里,并在有限的时间内完成它. 就像做建筑工程一样,其实做IT也是可以量化的,可能有的人砌砖砌得慢一些,有的人快一些. 但是我们把整 ...
- linux mysql乱码问题
mysql,发现都是乱码,一堆问号,如下图: 查看mysql编码 需要修改mysql编码,打开/etc/my.cnf 文件 在下边添加如下行 [client] default_character_se ...
- Django (十) 项目部署 1
阿里云部署项目 1, 购买阿里云ECS云服务器(可免费试用1个月) 2, 阿里云实例更换为Ubuntu 3, 安全组配置 4, xshell远程连接 5, 创建虚拟环境: 5.1 linux基本命令 ...
- with rollup
实验吧的一道ctf题,这两天无聊,做做ctf题.在实验吧被一道也题卡了好久. 页面很简单就是一个登陆页面,按照之前的经验觉得应该是注入吧.再看题猜测应该是绕waf之类的. 查看页面源码找到了提供的源代 ...
- ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined) C
Molly Hooper has n different kinds of chemicals arranged in a line. Each of the chemicals has an aff ...
- UG 常用设置
Q01:UG制图,添加基本视图之后的中心线怎么去掉? A01:“菜单-->文件-->首选项-->制图-->视图-->公共-->常规-->□带中心线创建”,取消 ...
- Metasploits之ms10_018
漏洞详情:https://technet.microsoft.com/library/security/ms10-018 一准备: 1:kali Linux系统 192.168.195.129 2:W ...
- python __new__ __init__ 区别
参数 __new__的第一个占位参数是class对象 __init__的第一个占位参数是class的实例对象 其他的参数应一致 作用 __new__ 用来创建实例,在返回的实例上执行__init__, ...
- keil_rtx调试技巧
超级循环结构的程序调试一般依赖于断点,单步,查看变量和内存变量(keil中的Memory Window 或者 Watch window):而带微操作系统的程序由于加了这个中间层调试方法可能传统的有些区 ...