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)的一发神犇的 只要判断这个子串之前被标记的记号(也就是他属于第几个串)和这次转移到的是否相同 如果不同就说明该子串属于多个串 直接标记- ...
随机推荐
- VRTK3.3.0-004传送
直线传送: 一.无高度变换传送(VRTK_BasicTeleport) 1丶继续在VRScripts下创建空物体PlayArea,用来挂在传送相关脚本:创建Plane作为传送地面 2丶在PlayAre ...
- [!] No `Podfile' found in the project directory.
1.cd ios/ 2.vim Podfile(创建Podfile)且输入内容 source'https://github.com/CocoaPods/Specs.git'platform:ios,' ...
- VLAN-2-私有VLAN
好的设计方式通常要求工程师为每个vlan使用一个ip子网.然而在有些情况下,将设备分割到许多小VLAN中以增加安全性的需求,与节省可用子网的目标相互冲突.通过使用私有vlan,交换机能够分 ...
- 普通平衡树与文艺平衡树的splay代码
主要综合借鉴了yyb和马前卒两位大佬的. //普通平衡树 #include <cstdio> #include <cctype> #include <cstring> ...
- js判断网页访问设备类型
有时候我们会需要来根据不同的设备访问进行不同的操作,在网上找了一下,主要是根据Navigator对象, if(/Android|Windows Phone|webOS|iPhone|iPod|Blac ...
- elasticsearch的模糊查询
https://blog.csdn.net/a772304419/article/details/78951561
- iis日志存放位置 及 查看方法
IIS:控制面板--管理工具--internet信息服务 网站的IIS日志是在空间里面看的.要登陆到空间里面的一个IIS日志里面看.IIS日志一般都很大的.看会有点.. 一.应用程序日志.安全日志.系 ...
- log4j日志工具类
/** * log4j日志Util */public class LogUtil { private static Logger logger=null; static{ StackTraceElem ...
- thinkphp写的登录注册的小demo
和asp.net类似,一个FormAction对应Form文件夹 demo结构: ‘ 对于项目结构有疑问的: http://www.thinkphp.cn/document/60.html login ...
- IOS生成UUID
/** * 生成GUID */ + (NSString *)generateUuidString{ // create a new UUID which you own CFUUIDRef uuid ...