这一题我们考虑一个最裸的算法:

我们设$dp[i][j][k][l]$表示当前棋子在$(i,j)$且空格在$(k,l)$时的最小步数

然后显然随便转移一下就好了,时间复杂度为$O(q(nm)^2)$。可以获得$80$分的好成绩(我自测的时候只打了这个)

我们发现这一题有一些很优秀的性质:

首先整个图是静态的,且起点,终点,出现空格的位置均非障碍物。

那么对于这个性质,我们做一些微小的预处理。

考虑到当空格与目标棋子四相邻的时候,棋子才能往空格内移动。那么整个走棋的过程可以理解为:调整空格位置-移动棋子到空格里-调整空格位置

我们设$f[i][j][k][l]$表示在不经过$(i,j)$的情况下,将空格从$(i+wx[k],j+wy[k])$移动到$(i+wx[l],j+wy[l])$的最小步数,其中$wx,wy$满足$|wx[i]+wy[i]|=1$,显然有四种组合。

对于每一个$f[i][j][k][l]$,我们通过一次$bfs$去求解。

预处理$f$的时间复杂度显然为$O(16nm)$。

下面考虑每一组询问:

若起点和终点的坐标相同,那么显然输出$0$就好了。

若起点和终点坐标不相同,我们先考虑将空格移动到起点四相邻的位置,所需要的最小步数显然可以通过一次$bfs$求得。

然后我们设$d[i][j][k]$表示当前棋子在$(i,j)$时,空格在$(i+wx[k],j+wy[k])$的最小步数。

显然随便$bfs$就可以进行更新了。最后的答案显然是$min(d[tx][ty][])$。

时间复杂度$O(16nm+4qnm)$。跑得飞快。

 #include<bits/stdc++.h>
#define M 32
#define INF 16843009
using namespace std;
int n,m,q,mp[M][M]={},dis[M][M]={},d[M][M][]={},f[M][M][][]={};
const int wx[]={,,,-};
const int wy[]={,,-,};
queue<int> qx,qy,qk;
void bfs(int X,int Y){
memset(dis,,sizeof(dis));
qx.push(X); qy.push(Y); dis[X][Y]=;
while(!qx.empty()){
X=qx.front(); qx.pop();
Y=qy.front(); qy.pop();
for(int i=;i<;i++){
int _x=X+wx[i],_y=Y+wy[i];
if(mp[_x][_y]&&dis[_x][_y]>dis[X][Y]+){
dis[_x][_y]=dis[X][Y]+;
qx.push(_x); qy.push(_y);
}
}
}
}
void move(int x,int y){
memset(dis,,sizeof(dis));
qx.push(x); qy.push(y); dis[x][y]=;
while(!qx.empty()){
x=qx.front(); qx.pop();
y=qy.front(); qy.pop();
for(int i=;i<;i++){
int _x=x+wx[i],_y=y+wy[i];
if(mp[_x][_y]&&dis[_x][_y]>dis[x][y]+){
dis[_x][_y]=dis[x][y]+;
qx.push(_x); qy.push(_y);
}
}
}
} void bfs(){
while(!qx.empty()){
int x=qx.front(); qx.pop();
int y=qy.front(); qy.pop();
int k=qk.front(); qk.pop();
for(int i=;i<;i++){
int _x=x+wx[i],_y=y+wy[i];
if(mp[_x][_y]==) continue;
if(d[_x][_y][(i+)&]>d[x][y][k]+f[x][y][k][i]+){
d[_x][_y][(i+)&]=d[x][y][k]+f[x][y][k][i]+;
qx.push(_x); qy.push(_y); qk.push((i+)&);
}
}
}
} int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) scanf("%d",&mp[i][j]); for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]){
mp[i][j]=;
for(int k=;k<;k++)
if(mp[i+wx[k]][j+wy[k]]){
bfs(i+wx[k],j+wy[k]);
for(int l=;l<;l++)
f[i][j][k][l]=dis[i+wx[l]][j+wy[l]];
}
mp[i][j]=;
} while(q--){
int ex,ey,sx,sy,tx,ty;
cin>>ex>>ey>>sx>>sy>>tx>>ty;
if(sx==tx&&sy==ty){
printf("0\n");
continue;
}
mp[sx][sy]=;
move(ex,ey);
mp[sx][sy]=;
memset(d,,sizeof(d));
for(int i=;i<;i++)
if(mp[sx+wx[i]][sy+wy[i]]){
qx.push(sx);
qy.push(sy);
qk.push(i);
d[sx][sy][i]=dis[sx+wx[i]][sy+wy[i]];
}
bfs();
int minn=INF;
for(int i=;i<;i++)
minn=min(minn,d[tx][ty][i]);
if(minn==INF) printf("-1\n");
else cout<<minn<<endl;
}
}

【NOIP2013】 华容道 bfs预处理+bfs的更多相关文章

  1. BZOJ-1189 紧急疏散evacuate BFS预处理+最大流+二分判定+神建模!!

    绝世污题,垃圾题,浪费我一整天青春! 1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1262 ...

  2. HDU - 1430 魔板 (bfs预处理 + 康托)

    对于该题可以直接预处理初始状态[0, 1, 2, 3, 4, 5, 6, 7]所有可以到达的状态,保存到达的路径,直接打印答案即可. 关于此处的状态转换:假设有初始状态为2,3,4,5,0,6,7,1 ...

  3. 【2016 ICPC亚洲区域赛北京站 E】What a Ridiculous Election(BFS预处理)

    Description In country Light Tower, a presidential election is going on. There are two candidates,   ...

  4. HDU 3533 Escape(BFS+预处理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3533 题目大意:给你一张n* m的地图,人在起点在(0,0)要到达终点(n,m)有k(k<=10 ...

  5. bzoj 1415(概率dp和bfs预处理)

    感觉挺经典的一道题目. 先用 bfs 预处理下一步走到的位置.因为每一步走法都是固定的,所以可以用dp的方法来做. 1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  M ...

  6. [NOIP2013]华容道 题解(搜索)

    [NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...

  7. [NOIP2013]华容道 题解

    [NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...

  8. luogu P1979 [NOIP2013] 华容道

    传送门 这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定 所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空 ...

  9. LOJ2613 NOIP2013 华容道 【最短路】*

    LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...

随机推荐

  1. jQuery使用大全

    我的程序人生 提供基于Lesktop的IM二次开发,联系QQ:76159179 CnBlogs Home New Post Contact Admin Rss Posts - 476  Article ...

  2. 在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了?

    在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了? 在删除成功后,加上这句话就可以了:$("#dg").datagrid ...

  3. noip第8课作业

    1.     计算书费 [问题描述]下面是一个图书的单价表: 计算概论 28.9 元/本 数据结构与算法 32.7 元/本 数字逻辑 45.6元/本 C++程序设计教程 78 元/本 人工智能 35  ...

  4. c++中sort()及qsort()的用法总结

    当并算法详解请见点我 想起来自己天天排序排序,冒泡啊,二分查找啊,结果在STL中就自带了排序函数sort,qsort,总算把自己解脱了~ 所以自己总结了一下,首先看sort函数见下表: 函数名 功能描 ...

  5. java web前端easyui(layout+tree+双tabs)布局+树+2个选项卡tabs

    1.列出要实现的样式: 2.实现的代码: 分三大部分: 1):页面主体部分:mian.vm <html> <head> <title>Ks UI</title ...

  6. Python学习-21.Python的代码注释

    在Python中有两种注释,一种是普通注释,另一种是文档注释. 普通注释是使用#开头 print('output something') # here is comment 而Python中多行注释也 ...

  7. Elasticsearch 的一些关键概念

    我更喜欢把 Elasticsearch 作为一种 nosql 去理解,它的一些开发概念和 MongoDB 以及 Redis 没有太大的区别,不过了解 Elasticsearch 中的一些核心概念对于你 ...

  8. SQL导入的方法,网上看到的

    -------这是一个新表,准备用来导入的表 CREATE TABLE CSVTable( Name NVARCHAR(MAX), Email NVARCHAR(MAX), Area NVARCHAR ...

  9. C#委托和事件的使用的意义

    转载自:https://www.cnblogs.com/yinqixin/p/5056307.html 每一个初学C#的程序猿,在刚刚碰到委托和事件的概念时,估计都是望而却步,茫然摸不到头脑的.百度一 ...

  10. 在Docker中运行纸壳CMS并配置使用MySql

    纸壳CMS是基于ASP.Net Core开发的可视化内容管理系统,可以跨平台部署,可以在容器中运行.接下来看看如何在docker中运行纸壳CMS. GitHub:https://github.com/ ...