题目背景

NOIP2013 提高组 Day2 试题。

题目描述

小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。

小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的: 
1. 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的; 
2. 有些棋子是固定的,有些棋子则是可以移动的; 
3. 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。 游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。

给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EXi 行第 EYi 列,指定的可移动棋子的初始位置为第 SXi 行第 SYi 列,目标位置为第 TXi 行第 TYi 列。

假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。

输入格式

第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;

接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。

接下来的 q 行,每行包含 6 个整数依次是 EXi、EYi、SXi、SYi、TXi、TYi,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。

输出格式

输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出 -1。

样例数据 1

输入

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

输出

2
-1

备注

【样例说明】 
棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。

1.第一次游戏,空白格子的初始位置是 (3,2)(图中空白所示),游戏的目标是将初始位置在 (1,2) 上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置 (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。

杂谈:

我。。。(此处省略1000字吐槽)

在考场上就算想到正解我也不会去写的,写正解的时间是暴力的4倍。。。

我先写的DFS发现DFS不仅慢而且不好处理,于是弃疗写BFS在洛谷上得了80分,由于对洛谷飞快的评测机实在不放心又在接近CCF老爷机的机子上测得了70分(这个应该准确些),于是一个晚上没了。。。

然后第二天刚了一上午终于把正解调出来了。。。

解析:

先说暴力70分怎么写,直接BFS,记录的状态就是当前空格子和目标格子所在位置,非常好写且信价比高。

然后是正解。因为只有空白块在指定棋子的旁边,指定棋子才能移动,而且指定棋子每次移动后,空白块仍然与指定棋子相邻。所以令]表示指定棋子在,空白块在与指定棋子相邻的方向,要将空白块移动到与指定棋子相邻的方向需要的步数。那么首先把预处理出来,在每一次讯问中,把空白格移到指定棋子相邻的存在的格子,做一次spfa,就可以了。

spfa:令表示指定棋子在,空白块在与指定棋子相邻的方向的状态需要的最少步数。转移显然,是要移动到的方向,表示指定格子要向方向走,指移动后空白块在与指定棋子相邻的方向,即是的相反方向,那么

至于复杂度,我无法准确说出来,还请各位dalao赐教。

总结:

函数内变量名不要重复!否则很难检查到!

数组在不超内存的情况定大点,否则可能会有边界问题!否则很难检查到!

代码(70分):

#include <bits/stdc++.h>
using namespace std;const int Max=31;
const int fx[5]={0,1,0,-1,0};
const int fy[5]={0,0,1,0,-1};
int n,m,ans,q;
int sx,sy,tx,ty,x,y;
int num[Max][Max],vis[Max][Max][Max][Max];
struct shu{int x,y,sx,sy,step;};
shu p[5000001];inline int get_int()
{int x=0,f=1;char c;for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());if(c=='-') f=-1,c=getchar();for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';return x*f;
}inline int bfs()
{int head=0,tail=1;p[1].x=x,p[1].y=y,p[1].sx=sx,p[1].sy=sy;while(head<tail){int x=p[++head].x,y=p[head].y;for(int i=1;i<=4;i++){int x1=x+fx[i],y1=y+fy[i],xx=p[head].sx,yy=p[head].sy;if(x1==xx&&y1==yy) xx=x,yy=y;if(x1<1||x1>n||y1<1||y1>m||!num[x1][y1]||vis[x1][y1][xx][yy]) continue;tail++;p[tail].sx=xx,p[tail].sy=yy,p[tail].x=x1,p[tail].y=y1,p[tail].step=p[head].step+1;vis[x1][y1][xx][yy]=1;if(p[tail].sx==tx&&p[tail].sy==ty) return p[tail].step;}}return -1;
}int main()
{n=get_int(),m=get_int(),q=get_int();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)num[i][j]=get_int();while(q--){memset(vis,0,sizeof(vis));x=get_int(),y=get_int(),sx=get_int(),sy=get_int(),tx=get_int(),ty=get_int();if(sx==tx&&sy==ty) cout<<"0\n";else{ans=bfs();cout<<ans<<"\n";}}return 0;
}

代码(100分):

#include <bits/stdc++.h>
using namespace std;const int Max=35;
const int fx[5]={0,1,0,-1};
const int fy[5]={1,0,-1,0};
int n,m,q,head,tail,tot,ans;
int num[Max][Max],dis[Max][Max][5],move[Max][Max][5][5];
bool vis[Max][Max],v[Max][Max][5];
int p[1000000][5],d[1000000][5];inline void bfs(int x,int y,int k1,int k2)
{int sx=x+fx[k1],sy=y+fy[k1],tx=x+fx[k2],ty=y+fy[k2];if((!num[sx][sy])||(!num[tx][ty])) return;head=0,tail=1;p[1][1]=sx,p[1][2]=sy;memset(vis,0,sizeof(vis));vis[x][y]=vis[sx][sy]=1;while(head<tail){head++;int xx=p[head][1],yy=p[head][2];for(int i=0;i<=3;i++){int x1=xx+fx[i],y1=yy+fy[i];if(!vis[x1][y1] && num[x1][y1]){vis[x1][y1]=1;p[++tail][1]=x1,p[tail][2]=y1,p[tail][0]=p[head][0]+1;if(x1==tx&&y1==ty) {move[x][y][k1][k2]=p[tail][0];return;}}}}
}inline void pre()
{memset(move,43,sizeof(move));for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(num[i][j])for(int k=0;k<=3;k++)for(int l=0;l<=3;l++)if(l==k) move[i][j][k][l]=0;else bfs(i,j,k,l);
}inline void calc(int x,int y,int sx,int sy)
{head=0,tail=1,tot=0;p[1][1]=x,p[1][2]=y,p[1][0]=0;memset(vis,0,sizeof(vis));vis[x][y]=vis[sx][sy]=1;while(head<tail){head++;int xx=p[head][1],yy=p[head][2];for(int i=0;i<=3;i++){int x1=xx+fx[i],y1=yy+fy[i];if(num[x1][y1]&&!vis[x1][y1]){vis[x1][y1]=1;p[++tail][0]=p[head][0]+1;p[tail][1]=x1,p[tail][2]=y1;}else if(x1==sx&&y1==sy) d[++tot][1]=x1,d[tot][2]=y1,d[tot][0]=p[head][0],d[tot][3]=(i+2)%4;}}
}inline void SPFA()
{memset(v,0,sizeof(v));for(int i=1;i<=tot;i++) dis[d[i][1]][d[i][2]][d[i][3]]=d[i][0],v[d[i][1]][d[i][2]][d[i][3]]=1;head=0,tail=tot;while(head<tail){head++;int x=d[head][1],y=d[head][2];v[x][y][d[head][3]]=0;for(int i=0;i<=3;i++){int x1=x+fx[i],y1=y+fy[i];if(dis[x1][y1][(i+2)%4] > dis[x][y][d[head][3]]+move[x][y][d[head][3]][i]+1){dis[x1][y1][(i+2)%4]=dis[x][y][d[head][3]]+move[x][y][d[head][3]][i]+1;if(!v[x1][y1][(i+2)%4]){tail++;d[tail][1]=x1,d[tail][2]=y1,d[tail][3]=(i+2)%4;v[x1][y1][(i+2)%4]=1;}} }}
}int main()
{scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) scanf("%d",&num[i][j]);pre();while(q--){int x,y,sx,sy,tx,ty;scanf("%d%d%d%d%d%d",&x,&y,&sx,&sy,&tx,&ty);if(sx==tx&&sy==ty) {cout<<"0\n";continue;}memset(dis,43,sizeof(dis));calc(x,y,sx,sy);SPFA();ans=dis[0][0][0];for(int i=0;i<=3;i++) ans=min(ans,dis[tx][ty][i]);if(ans==dis[0][0][0]) cout<<"-1\n";else cout<<ans<<"\n";}return 0;
}

【NOIP2013提高组】华容道相关推荐

  1. 【题解】P1979 [NOIP2013 提高组] 华容道(SPFA,BFS,常数优化)

    [题解]P1979 [NOIP2013 提高组] 华容道 最近打比赛次次挂..平均每周得被至少一场比赛打击一次(这周好不容易 ABC 打的还行模拟赛又挂--)心烦意乱.写篇题解疏散一下内心的苦闷(雾) ...

  2. P1979 [NOIP2013 提高组] 华容道

    题目来源 [NOIP2013 提高组] 华容道 - 洛谷 题目考点 搜索   图论 题目 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, ...

  3. NOIP2013 提高组复赛解题报告

    NOIP2013 提高组复赛 day1 day\;1 1002. 火柴排队 贪心+数据结构/归并排序 这个"相邻交换"让我联想到了NOIP2012_day1_task2_game那 ...

  4. 【NOIP2013提高组】花匠

    题目背景 NOIP2013 提高组 Day2 试题. 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空 ...

  5. 【NOIP2013提高组】火柴排队

    题目背景 NOIP2013 提高组 Day1 试题 题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定 ...

  6. 【NOIP2013提高组】积木大赛

    题目背景 NOIP2013 提高组 Day2 试题 题目描述 春春幼儿园举办了一年一度的"积木大赛".今年比赛的内容是搭建一座宽度为 n 的大厦,大厦可以看成由 n 块宽度为 1  ...

  7. 【NOIP2013提高组T3】加分二叉树

    题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...

  8. [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)

    一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先.第一次写..表示各种乱.. 因为要求运输货物质量最大,所以路径一定是在最大生成树上的.然后 ...

  9. [NOIP2013] 提高组 洛谷P1979 华容道

    题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...

  10. NOIP2013提高组 day2

    1.积木大赛 题目描述 春春幼儿园举办了一年一度的"积木大赛".今年比赛的内容是搭建一座宽度为 n n n的大厦,大厦可以看成由 n n n块宽度为 1 1 1的积木组成,第 i ...

最新文章

  1. 反正我不信!马斯克谈元宇宙:没人愿意把屏幕贴脸上
  2. JavaScript(三)——函数、变量作用域、方法
  3. VTK:饼形图用法实战
  4. SVN入门:流程简介 安装配置 项目库配置 客户端 上线方案
  5. 徐坤用话剧震了我们一道
  6. Qt通过ODBC读取excel文件
  7. 数仓大法好!跨境电商 Shopee 的实时数仓之路
  8. 小米畅聊也将瞄准镜对向微信电话本
  9. L1-021. 重要的话说三遍-PAT团体程序设计天梯赛GPLT
  10. Centos7安装完毕后无法联网的解决方法
  11. 基于android下的amr转mp3
  12. 身份证二要素,帮你轻松搞定实名认证
  13. cisco ASA ios升级或恢复
  14. 网页版邮箱提取/采集软件
  15. ASP+AJAX实现分页效果[Z]
  16. 【报告分享】2021全球自由行报告-中国旅游研究院马蜂窝(附下载)
  17. 单机搭建Nacos集群
  18. 重定向与请求转发的区别及什么时候使用
  19. 【GitLab】GitLab数据自动删除、自动备份
  20. 博奥智源科技浅谈医院采购合理用药系统功能详细设计

热门文章

  1. 32*32 点阵字库 linux,点阵字库-linux_wuliqiang-ChinaUnix博客
  2. 服装设计与工程_百度百科
  3. 【数学建模算法汇总】
  4. 高等代数第3版下 [丘维声 著] 2015年版_微电子电路设计 第4版 电子书
  5. 软件著作权申请教程模板材料下载
  6. 微信小程序申请 软件著作权(其它 软件,小程序都可以)
  7. 抖音python上的代码_抖音代码舞python实例代码
  8. FreeFileSync 文件夹比较与同步软件
  9. Tiled Map的使用说明
  10. 蚂蚁笔记 linux安装教程,简年14:蚂蚁笔记(Leanote)快速部署指南