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

我们设$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. 讲讲我在Windows10(uwp)开发中遇到的一些坑.

    7月29日发布的Windows10正式版,当天安装好以后,在网络不太好的情况下,经过多次尝试终于装上了Visual Studio 2015和Windows 10 10240的SDK.这两周一直在开发U ...

  2. 客户被绑,蒙眼,惊问:“想干什么?” 对方不语,鞭笞之,客户求饶:“别打,要钱?” 又一鞭,“十万够不?” 又一鞭,“一百万?” 又一鞭。客户崩溃:“你们TMD到底要啥?” “要什么?...

    1.  客户被绑,蒙眼,惊问:“想干什么?”     对方不语,鞭笞之,客户求饶:“别打,要钱?”     又一鞭,“十万够不?”     又一鞭,“一百万?”     又一鞭.客户崩溃:“你们TMD ...

  3. 右值引用和std::move函数(c++11)

    1.对象移动 1)C++11新标准中的一个最主要的特性就是移动而非拷贝对象的能力 2)优势: 在某些情况下,从旧内存拷贝到新内存是不必要的,此时对对象进行移动而非拷贝可以提升性能 有些类如IO类或un ...

  4. C++中的关键字用法--- 四种强制类型转换的总结

    四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast 1. C风格的强制类型转换(Type Cast)很简单,不管什么类 ...

  5. opencv学习_4(opencv基础数据结构 CvPoint & CvSize & CvRect & CvScalar & CvArr & CvMat)

    1:包含在cxcore/include/cxtypes.h头文件中. 2:CvPoint系列   -----(x,y) CvPoint:表示图像中的点 CvPoint2D32f:二维空间中的点 CvP ...

  6. Spring MVC 的@RequestParam注解和request.getParameter("XXX")

    在SpringMVC后台控制层获取参数的方式主要有两种,一种是request.getParameter("name"),另外一种是用注解@RequestParam直接获取.这里主要 ...

  7. eclipse快捷键(增加一些4连组合快捷键)

    http://www.blogjava.net/i369/articles/83309.html   ECLISPE的快捷键大全 Eclipse 常用快捷键收集2006年09月29日 星期五 12:0 ...

  8. mac下能同时安装两个版本的xcode吗

    http://www.cocoachina.com/bbs/read.php?tid-288160-page-1.html

  9. centos:开启和关闭selinux

    5.4. Enabling and Disabling SELinux Use the /usr/sbin/getenforce or /usr/sbin/sestatus commands to c ...

  10. bootstrap-treeview + angular 使用

    bootstrap-treeview是什么 bootstrap-treeview是一款效果非常酷的基于bootstrap的jQuery多级列表树插件. 怎样使用bootstrap-treeview 插 ...