版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
Analysis
拿到题后首选搜索
然后人家暴力都是七八十
我只有5分???
不知道哪里dfs挂了
至于一开始想到的bfs
因为害怕死循环而不知道怎么打标记所以弃了
翻了神仙的题解后,才意识到
bfs有个重要的性质,第一次访问到的节点到达它的距离一定最小
后面再到达就不优了,这个不仅可以用于剪枝,而且还可以避免重复走的情况
然后对于当前状态有用的就是现在在的位置和指定格子所在的位置,四维存一下即可(有点类似记忆化)
正解:
考虑q次询问中不变的是哪些。
由于棋盘是不会变化的,而指定格子能移动当且仅当空白格子在其上/下/左/右。那么我们就可以预处理出,每个格子作为指定格子时,空白格子在其四个方向上的状态
状态与状态之间建立关系
具体来说:
当前空格在指定格子下方,假定状态为
现在要转移到空格在指定格子左方,即
而所需要的最小步数就可以用BFS求出
这样将状态都处理出来后,对每个状态进行编号,建图
然后跑最短路
具体来说:
由于给定的空格位置和指定格子可能一开始并不相邻
我们需要先做一遍BFS将空格位置移到指定格子的四个方向(相当于有一个源点向这四个点连边,而最后的答案指定格子也可能在目标格子的四个方向,同理操作即可)
复杂度分析,,
不会,,
Code
#include<bits/stdc++.h>
#define in read()
#define re register
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<1)+(res<<3)+(ch^48);
ch=getchar();
}
return f==1?res:-res;
}
const int N=35;
int n,m,q;
int a[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int f[N][N];
const int M=4009;
int nxt[M<<4],head[M],to[M<<4],w[M<<4],ecnt=0;
int dis[M<<2];
inline void add(int x,int y,int z){
// printf("u=%d v=%d val=%d\n",x,y,z);
nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;w[ecnt]=z;
}
inline int get_num(int x,int y){
y--;
return (x-1)*m+y<<2;
}
#define mp make_pair
void BFS(int ex,int ey,int px,int py,int d){
// printf("px=%d py=%d ex=%d ey=%d\n",px,py,ex,ey);
memset(f,-1,sizeof(f));
f[ex][ey]=0;
f[px][py]=1;
queue<pair<int,int> > q;
q.push(mp(ex,ey));
while(!q.empty()){//预处理出来空格位置到其他位置的最短步数
int x=q.front().first,y=q.front().second;q.pop();
for(re int i=0;i<4;++i){
int xx=x+dx[i];
int yy=y+dy[i];
if(f[xx][yy]!=-1) continue;
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]){
f[xx][yy]=f[x][y]+1;
q.push(mp(xx,yy));
}
}
}
if(d==-1) return;
int num=get_num(px,py);
// printf("px=%d py=%d num=%d\n",px,py,num);
for(re int i=0;i<4;++i){//状态转移
int x=px+dx[i];
int y=py+dy[i];
// x>=1&&x<=n&&y>=1&&y<=m&&
if(f[x][y]>0)
add(num+d,num+i,f[x][y]);
}
add(num+d,get_num(ex,ey)+(d+2)%4,1);
}
int INF;
bool vis[M<<2];
void spfa(int sx,int sy){
queue<int> q;
memset(vis,0,sizeof(vis));
memset(dis,127/3,sizeof(dis));
INF=dis[0];
for(re int i=0;i<4;++i){
int x=sx+dx[i];
int y=sy+dy[i];
if(x>=1&&x<=n&&y>=1&&y<=m&&f[x][y]!=-1){
int num=get_num(sx,sy)+i;
dis[num]=f[x][y];
q.push(num);
// printf("tmp=%d dis=%d\n",num,dis[num]);
}
}
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(re int e=head[u];e;e=nxt[e]){
int v=to[e];
if(dis[v]>dis[u]+w[e]){
dis[v]=dis[u]+w[e];
if(vis[v]) continue;
vis[v]=1;
q.push(v);
}
}
}
}
int main(){
n=in;m=in;q=in;
for(re int i=1;i<=n;++i)
for(re int j=1;j<=m;++j)
a[i][j]=in;
for(re int i=1;i<=n;++i)
for(re int j=1;j<=m;++j)if(a[i][j]){
if(a[i-1][j])BFS(i-1,j,i,j,0);
if(a[i][j+1])BFS(i,j+1,i,j,1);
if(a[i+1][j])BFS(i+1,j,i,j,2);
if(a[i][j-1])BFS(i,j-1,i,j,3);
}
for(re int i=1;i<=q;++i){
int ex=in,ey=in,sx=in,sy=in,tx=in,ty=in;
if(sx==tx&&sy==ty){printf("0\n");continue;}
BFS(ex,ey,sx,sy,-1);
spfa(sx,sy);
int ans=INF;
for(re int j=0;j<4;++j)
ans=min(ans,dis[get_num(tx,ty)+j]);
if(ans>=INF) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}