2018/7/16 YMOI模拟 NOIP2013D2T3华容道
题目描述 Description
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
- 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
- 有些棋子是固定的,有些棋子则是可以移动的;
- 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。 游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。
给定一个棋盘,游戏可以玩
q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i
次玩的时候,空白的格子在第 EX_i 行第 EY_i 列,指定的可移动棋子的初始位置为第 SX_i 行第 SY_i 列,目标位置为第 TX_i
行第 TY_i 列。
假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。
输入描述 Input Description
第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;
接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。
接下来的 q 行,每行包含 6 个整数依次是 EX_i、EY_i、SX_i、SY_i、TX_i、TY_i,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。
输出描述 Output Description
输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出-1。
样例输入 Sample Input
3 4 2
0 1 1 1
0 1 1 0
0 1 0 0
3 2 1 2 2 2
1 2 2 2 3 2
样例输出 Sample Output
2
-1
数据范围及提示 Data Size & Hint
【样例说明】
棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。
第一次游戏,空白格子的初始位置是 (3, 2)(图中空白所示),游戏的目标是将初始位置在(1, 2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2, 2)(图中红色的格子)上。
移动过程如下:

第二次游戏,空白格子的初始位置是(1, 2)(图中空白所示),游戏的目标是将初始位置在(2, 2)上的棋子(图中绿色圆圈所示)移动到目标位置 (3, 2)上。

要将指定块移入目标位置,必须先将空白块移入目标位置,空白块要移动到目标位置,必然是从位置(2,2)上与当前图中目标位置上的棋子交换位置,之后能与空白块交换位置的只有当前图中目标位置上的那个棋子,因此目标棋子永远无法走到它的目标位置,游戏无法完成。
【数据范围】
对于 30%的数据,1 ≤ n, m ≤ 10,q = 1;
对于 60%的数据,1 ≤ n, m ≤ 30,q ≤ 10;
对于 100%的数据,1 ≤ n, m ≤ 30,q ≤ 500。
——————————————————————————————————————————————————————————————————————————
思路一(虽然没错但是会TLE)
一看到题目,联想到以前做过的八数码。于是可以想到把空白块当作可以自由移动的单位进行BFS。由于想不到什么优化措施,所以就敲了一段大爆搜……虽然TLE是意料之中,但是没想到竟然能拿到70分(那这就说明我离正解不远了/误)
蒟蒻的大爆搜就别看了qwq
——————————————————————————————————————————————————————————————————————————
思路二(正解)
整理一下为什么思路一的BFS是错的。
在一个规模较小的数据范围内,思路一的BFS是可以在1s内得出结论的……但是很不幸,虽然出题人很善良的给了70分(是不是没卡掉),但是爆搜还是没有前途的;
思路一的BFS缺陷就是,白块是以一种玄妙不可预测的路线行进的(误)。在搜索的时候会浪费很多时间在根本不可能的情况上(不做无法实现的梦)。
所以在冥(ming)思(le)苦(ti)想(jie)以后想到了绝妙的算法!
对于最优的操作,有一个前提是空白块一定要先移动到钦点块的旁边。然后空白块和钦点块再作为一个整体移动。
空白块和钦点块的移动可以用SPFA来求最短路径。建图的方法就是把空白块和钦点块的位置的状态看作一个点,再把每个状态之间互相转换的过程看作边,在这个图里跑一边SPFA就可以轻松求出正解!
以下是蒟蒻敲了一个下午的代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define MAXN 31
#define MAXM 40001
#define INF 0x3f3f3f3f
int n,m,q,num[MAXN][MAXN][],tot,cnt,head[MAXM],vis[MAXN][MAXN],ex,ey,sx,sy,tx,ty,dis[MAXM],used[MAXM],mp[MAXN][MAXN];
const int dx[]={,-,,},dy[]={,,,-};
struct Edge
{
int to,dis,next;
}e[MAXM];
struct ZT{int x,y,steps;};
void add(int from,int to,int dis)
{
e[++cnt].next=head[from];
e[cnt].to=to;
e[cnt].dis=dis;
head[from]=cnt;
}
int bfs(int ax,int ay,int bx,int by,int cx,int cy)
{
if(ax==bx&&ay==by) return ;
memset(vis,,sizeof(vis));
queue<ZT>Q;
while(!Q.empty()) Q.pop();
Q.push((ZT){ax,ay,});
vis[ax][ay]=vis[cx][cy]=;
while(!Q.empty())
{
ZT u=Q.front();Q.pop();
if(u.x==bx&&u.y==by) return u.steps;
for(int i=;i<;i++)
{
int x=u.x+dx[i],y=u.y+dy[i];
if(x>=&&x<=n&&y>=&&y<=m&&mp[x][y]&&!vis[x][y])
{
Q.push((ZT){x,y,u.steps+});
vis[x][y]=;
if(x==bx&&y==by) return u.steps+;
}
}
}
return INF;
}
void init()
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<;k++)
if(mp[i][j]&&mp[i+dx[k]][j+dy[k]])
num[i][j][k]=++tot;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<;k++)
if(num[i][j][k])
add(num[i][j][k],num[i+dx[k]][j+dy[k]][k^],);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<;k++)
for(int l=;l<;l++)
if(l!=k&&num[i][j][k]&&num[i][j][l])
add(num[i][j][k],num[i][j][l],bfs(i+dx[k],j+dy[k],i+dx[l],j+dy[l],i,j));
}
int spfa()
{
queue<int>Q;
if(sx==tx&&sy==ty) return ;
for(int i=;i<=tot;i++) dis[i]=INF;
for(int k=;k<;k++)
{
if(num[sx][sy][k])
{
dis[num[sx][sy][k]]=bfs(ex,ey,sx+dx[k],sy+dy[k],sx,sy);
Q.push(num[sx][sy][k]);
}
}
while(!Q.empty())
{
int u=Q.front();Q.pop();
used[u]=;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(dis[v]>dis[u]+e[i].dis)
{
dis[v]=dis[u]+e[i].dis;
if(!used[v])
{
Q.push(v);
used[v]=;
}
}
}
}
int ans=INF;
for(int k=;k<;k++)
{
if(num[tx][ty][k]) ans=min(ans,dis[num[tx][ty][k]]);
}
return ans==INF?-:ans;
}
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]);
init();
while(q--)
{
scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
printf("%d\n",spfa());
}
return ;
}
118行orz
这道题做的我要死了orz
顺便吐槽一下为什么NOIP2013D2前两道都是普及的水题,到最后一道题就这么难orz
2018/7/16 YMOI模拟 NOIP2013D2T3华容道的更多相关文章
- 2018.10.16 NOIP模拟 华莱士(并查集)
传送门 按照题意模拟维护最小的环套树森林就行了. 然而考试的时候naivenaivenaive瞎写了一个错误的贪心. 代码
- 2018.10.16 NOIP模拟赛解题报告
心路历程 预计得分:\(100 + 100 + 20 = 220\) 实际得分:\(100 + 100 + 30 = 230\) 辣鸡模拟赛.. T1T2都是一眼题,T3考验卡常数还只有一档暴力分. ...
- EZ 2018 03 16 NOIP2018 模拟赛(四)
链接:http://211.140.156.254:2333/contest/64 我去掉了一百多分! 这次的题目怎么说呢,特别水,但是就是出现了一些很逗的错误导致炸裂. 最好笑的是SB的不只我一个: ...
- 2018.10.16 NOIP模拟 长者(主席树+hash)
传送门 考试的时候开始sb的以为需要可持久化trietrietrie树,发现建树时空都是O(n2)O(n^2)O(n2)的. 然后发现由于每次只从原来的字符串改一个字符. 因此直接主席树维护区间has ...
- 2018.10.16 NOIP模拟 膜法(组合数学)
传送门 原题,原题,全TM原题. 不得不说天天考原题. 其实这题我上个月做过类似的啊,加上dzyodzyodzyo之前有讲过考试直接切了. 要求的其实就是∑i=lr(ii−l+k)\sum _{i=l ...
- 10.16 NOIP模拟赛
目录 2018.10.16 NOIP模拟赛 A 购物shop B 期望exp(DP 期望 按位计算) C 魔法迷宫maze(状压 暴力) 考试代码 C 2018.10.16 NOIP模拟赛 时间:2h ...
- 5820. 【NOIP提高A组模拟2018.8.16】 非法输入(模拟,字符串)
5820. [NOIP提高A组模拟2018.8.16] 非法输入 (File IO): input:aplusb.in output:aplusb.out Time Limits: 1000 ms ...
- 2018.11.16 浪在ACM 集训队第五次测试赛
2018.11.16 浪在ACM 集训队第五次测试赛 整理人:李继朋 Problem A : 参考博客:[1]朱远迪 Problem B : 参考博客: Problem C : 参考博客:[1]马鸿儒 ...
- JZOJ5822 【NOIP提高A组模拟2018.8.16】 量子纠缠
这是一道很巧妙的题目. 今早,我调了好久,终于将它切掉了-- 题目 Description Input 第一行包含一个正整数 m,代表操作数. 接下来 m 行,每行可能有以下形式: 1 s 代表将数字 ...
随机推荐
- [转]Passing data between pages in JQuery Mobile mobile.changePage
本文转自:http://ramkulkarni.com/blog/passing-data-between-pages-in-jquery-mobile/ I am working on a JQue ...
- zepto.js常用操作
zepto.js是移动端的jquery,但是并没有提供所有与jquery类似的api.Zepto设计的目的是有一个5-10k的通用库.下载并快速执行.有一个熟悉通用的API,所以你能把你主要的精力放到 ...
- Java学生管理系统(连接数据库查询)超详细
这几天逼着交Java,借鉴各位师傅的做出来这么个简陋的东西,各位大师傅不要笑我.(学都没有学过Java的我,QAQ~) 下面针对的都是SQL Server系列的连接,如果你使用MySQL那么不必看关于 ...
- C#天气预报程序
首先要引用这个服务,http://www.webxml.com.cn/Webservices/WeatherWebService.asmx 出现对话框后,把中央气象的服务网址添加到里面 选择高级, 添 ...
- Socket网络通信之NIO
Socket网络通信之NIO NIO:new io ,java1.4开始推出的可非阻塞IO. java.nio 包,可解决BIO阻塞的不足 但比BIO学习.使用复杂. 可以以阻塞.非阻塞两种方式工作. ...
- windows远程连接Mac、Mac远程连接Mac、Mac连接Windows
最近因为要进行学习交流,需要用到远程连接,所以找了三种不同的方式,记录如下 1.Windows远程连接Mac 1.mac os x电脑设置 系统偏好设置-共享-勾选“远端管理”,然后在电脑设置—VNC ...
- 即将要被淘汰的兼容之--CSS Hack
css hack 条件注释法只在IE下生效<!--[if IE]>这段文字只在IE浏览器显示<![endif]-->只在IE6下生效<!--[if IE 6]>这段 ...
- 夜色的 cocos2d-x 开发笔记 00
第一次写博客,本人还是大二学生,纯新手,无论是文章的技术性,还是参考性,都不高,但却是根据我的经历,开发过的真实过程,对自己记载一些备忘的笔记,更希望也能帮到一些人. 本人用的win7 + vs201 ...
- MyBatis中sql语句
一.select <!-- 查询学生,根据id --> <select id="getStudent" parameterType="String&qu ...
- 常用HTML富文本编辑器
常用的HTML富文本编译器UEditor.CKEditor.TinyMCE.HTMLArea.eWebEditor.KindEditor简介 这篇文章主要介绍了常用的HTML富文本编译器UEdit ...