传送门

一个人推箱子,和之前的华容道中的棋子移动有异曲同工之妙,因为每次可以让人走到箱子的其他方向上,或者推一下箱子

所以状态可以设成\(f_{i,j,k}\),即箱子在\((i,j)\),人在\(k\)方向的状态是否存在,一开始也要把人移到箱子旁边作为初始状态,然后每次移动人到箱子其他方位或者推箱子

难点是如何快速判断人是否可以从一个方位移到另一个方位上去.如果可以,说明至少存在一条不经过箱子的路径使得这两个方位联通,那么这两个位置也就是在同一个点双连通分量里面,\(tarjan\)即可

然后我发现自己一开始并不会求点双

还把转移的一个过程写错了

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define inf 1061109567 using namespace std;
const int N=1500+10,M=N*N*4;
il LL rd()
{
re LL x=0,w=1;re char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[M<<1],nt[M<<1],hd[N*N],tot=1;
il void add(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
//++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int mm[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int n,m,qq,sx,sy,ex,ey,id[N][N],nxt[4]={2,3,0,1};
bool a[N][N],f[N][N][4],v[N][N];
int dfn[N*N],low[N*N],st[N*N],tp,ti,cnt;
vector<int> inb[N*N];
void tj(int x,int ffa)
{
dfn[x]=low[x]=++ti,st[++tp]=x;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(!dfn[y])
{
tj(y,x);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
++cnt;
while(tp)
{
int z=st[tp--];
inb[z].push_back(cnt);
if(y==z) break;
}
inb[x].push_back(cnt);
}
}
else if(y!=ffa)low[x]=min(low[x],dfn[y]);
}
}
il bool check(int x,int y)
{
for(int i=0,l1=inb[x].size();i<l1;i++)
for(int j=0,l2=inb[y].size();j<l2;j++)
if(inb[x][i]==inb[y][j]) return true;
return false;
}
struct nnn
{
int x,y,f;
}; int main()
{
n=rd(),m=rd(),qq=rd();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
id[i][j]=(i-1)*m+j;
for(int i=1;i<=n;i++)
{
char cc[N];
scanf("%s",cc+1);
for(int j=1;j<=m;j++)
{
a[i][j]=(cc[j]!='#');
if(cc[j]=='A') ex=i,ey=j;
else if(cc[j]=='B') sx=i,sy=j;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(!a[i][j]) continue;
for(int k=0;k<4;k++)
if(a[i+mm[k][0]][j+mm[k][1]]) add(id[i][j],id[i+mm[k][0]][j+mm[k][1]]);
}
tj(id[sx][sy],0);
a[sx][sy]=false;
queue<nnn> q;
v[ex][ey]=true;
q.push((nnn){ex,ey,0});
while(!q.empty())
{
int x=q.front().x,y=q.front().y;
q.pop();
for(int j=0;j<4;j++)
{
int xx=x+mm[j][0],yy=y+mm[j][1];
if(!a[xx][yy]||v[xx][yy]) continue;
v[xx][yy]=true;
q.push((nnn){xx,yy,0});
}
}
a[sx][sy]=true;
for(int j=0;j<4;j++)
{
int xx=sx+mm[j][0],yy=sy+mm[j][1];
if(v[xx][yy]&&a[xx][yy]) f[sx][sy][j]=true,q.push((nnn){sx,sy,j});
}
while(!q.empty())
{
int x=q.front().x,y=q.front().y,fx=q.front().f;
q.pop();
for(int j=0;j<4;j++)
{
int xx=x+mm[j][0],yy=y+mm[j][1];
if(j==nxt[fx]&&a[xx][yy]&&!f[xx][yy][fx])
{
f[xx][yy][fx]=true;
q.push((nnn){xx,yy,fx});
}
int bx=x+mm[fx][0],by=y+mm[fx][1];
if(f[x][y][j]||!check(id[bx][by],id[xx][yy])) continue;
f[x][y][j]=true;
q.push((nnn){x,y,j});
}
}
while(qq--)
{
int x=rd(),y=rd();
bool ok=f[x][y][0]|f[x][y][1]|f[x][y][2]|f[x][y][3]|(x==sx&&y==sy);
printf("%s\n",ok?"YES":"NO");
}
return 0;
}

luogu P4082 [USACO17DEC]Push a Box的更多相关文章

  1. Luogu P4082 [USACO17DEC]Push a Box 点双连通分量/圆方树

    (貌似有圆方树的做法,我写的是点双) 显然这道题就是直接搜索.定义状态为f[i][j][0~4]表示箱子在(i,j),人在某个方向推.然后问题就是怎么转向.我们发现如果要转向,必须是人走过一条不包括( ...

  2. [USACO17DEC]Push a Box

    https://www.zybuluo.com/ysner/note/1293166 题面 戳我 解析 挺不错的一道图论码量题. 可以借此回顾一下\(noip2013\)华容道. 思路和华容道差不多. ...

  3. 【BZOJ5138】[Usaco2017 Dec]Push a Box(强连通分量)

    [BZOJ5138][Usaco2017 Dec]Push a Box(强连通分量) 题面 BZOJ 洛谷 题解 这题是今天看到萝卜在做然后他一眼秒了,我太菜了不会做,所以就来做做. 首先看完题目,是 ...

  4. bzoj5138 [Usaco2017 Dec]Push a Box

    题目描述: bz luogu 题解: 暴力可以记录$AB$位置转移,这个时候状态是$n^4$的,无法接受. 考虑只记录$A$在$B$旁边时的状态,这个时候状态时$n^2$的. 所以说转移有两种,一种是 ...

  5. FlasActionScript3随学随机

    1.跳转页面代码.下载代码(new URLRequest(下载地址)): var request1:URLRequest=new URLRequest("http://www.baidu.c ...

  6. [游戏模版17] Win32 推箱子 迷宫

    >_<:Here introduce a simple game: >_<:resource >_<:only can push a box and finally ...

  7. POJ-1475-Pushing Boxes(BFS)

    Description Imagine you are standing inside a two-dimensional maze composed of square cells which ma ...

  8. js的基本的一些方法

    我们不是要背诵东西,只是因为这是我们生存的技能. 加油吧少年! 1.函数的块级作用域和函数的自我执行是一回事.!(function () { function box(){alert('hello') ...

  9. poj 1475 || zoj 249 Pushing Boxes

    http://poj.org/problem?id=1475 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=249 Pushin ...

随机推荐

  1. Java之相对路径找不到文件问题解决方法

    1.问题: 在程序需要通过相对路径引用文件,使用Junit可以正常执行,但是直接使用main方法找不到对应问题. 2.分析: 因为不同运行方式所使用的环境变量中的用户工作目录不同所致. 3.解决: 修 ...

  2. 洛谷P2397 yyy loves Maths VI (mode)

    P2397 yyy loves Maths VI (mode) 题目背景 自动上次redbag用加法好好的刁难过了yyy同学以后,yyy十分愤怒.他还击给了redbag一题,但是这题他惊讶的发现自己居 ...

  3. 51nod-1459-迷宫游戏

    题意:中文题目.. 解题思路:我的做法就是单源最短路中加个记录分数的数组,如果dis[i]到dis[x]的距离可以被优化,那就连记录分数的数组一起优化,如果第二条路和第一条路的距离相等,那就取最大的分 ...

  4. Flask-sqlacodegen

    ORM操作有两种方式. 1.模型迁移到数据库中生成表,codefirst:使用flask-migrate: 需要flask-script: from flask_script import Manag ...

  5. python列表和元组操作

    列表 列表(list)是python以及其他语言中最常用到的数据结构之一.Python使用中括号[ ]来解析列表.列表是可变的(mutable)—可以改变列表的内容. 定义列表 names = ['m ...

  6. BZOJ5286: [Hnoi2018]转盘 (线段树)

    题意 给你绕成一圈的物品共 \(n\) 个 , 然后从其中一个开始选 , 每次有两种操作 , 一是继续选择当前物品 , 二是选择这个后一个物品 . 选择后一个物品要求当前的时刻大于后一个的 \(T_i ...

  7. Hdoj 2187.悼念512汶川大地震遇难同胞——老人是真饿了 题解

    时间:2008年5月16日(震后第4天) 地点:汶川县牛脑寨 人物:羌族老奶奶 [转载整理]牛脑寨是一个全村600多人的羌族寨子,震后几天,这里依然能常常听到隆隆的声音,那是对面山上石头不断滑落的声音 ...

  8. 自学Linux Shell4.2-监测磁盘空间mount umount df du

    点击返回 自学Linux命令行与Shell脚本之路 4.2-监测磁盘空间mount umount  df du 1. 挂载存储媒体mount  移除存储媒体umount ls命令用于显示文件目录列表, ...

  9. 自学Linux Shell15.2-作业控制命令(jobs/bg/nice/renice/at/atp/atrm/crontab)

    点击返回 自学Linux命令行与Shell脚本之路 15.1-作业控制命令(jobs/bg/nice/renice/at/atp/atrm/crontab) 1  控制作业 1.1查看作业 (jobs ...

  10. 探测.yml

    liveness.yml #探测apiVersion: v1kind: Podmetadata: labels: test: liveness name: livenessspec: restartP ...