> 文章列表 > 一日一题:第三题--方格迷宫(DFS小难,不过很详细!)

一日一题:第三题--方格迷宫(DFS小难,不过很详细!)

一日一题:第三题--方格迷宫(DFS小难,不过很详细!)

题目描述

给定一个 n 行 m 列的方格矩阵。

行从上到下依次编号为 1∼n,列从左到右依次编号为 1∼m。

第 i 行第 j 列的方格表示为 (i,j)。

矩阵中的方格要么是空地(用 . 表示),要么是陷阱(用 # 表示)。

初始时,你位于方格 (x1,y1),你需要前往方格 (x2,y2)。

每次移动,你可以任选上、下、左、右四个方向之一,并沿该方向移动 1∼k 步。

从一个方格移动至相邻方格视为一步。

但是,你要保证在你的移动过程中不能走出矩阵,也不能进入陷阱方格。

请你计算从方格 (x1,y1)移动至方格 (x2,y2),所需要的最少移动次数

保证方格 (x1,y1) 和方格 (x2,y2)都是空地。

方格 (x1,y1) 和方格 (x2,y2)可能是同一个方格。

注意:注意区分本题中移动次数与移动步数的区别。

输入格式

第一行包含三个整数 n,m,k。

接下来 nn 行,每行包含 m 个字符,其中第 i 行第 j 个字符,要么是 .,表示方格 (i,j) 是空地;要么是 #,表示方格 (i,j)是陷阱。

最后一行包含四个整数 x1,y1,x2,y2。

输出格式

一个整数,表示所需要的最少移动次数

如果无法从方格 (x1,y1) 移动至方格 (x2,y2),则输出 -1

数据范围

前 66 个测试点满足 1≤n,m≤10。
所有测试点满足 1≤n,m,k≤1000,1≤x1,x2≤n,1≤y1,y2≤m。

输入样例1:

3 4 4
....
.
....
1 1 3 1

输出样例1:

3

输入样例2:

3 4 1
....
.
....
1 1 3 1

输出样例2:

8

输入样例3:

2 2 1
.#
#.
1 1 2 2

输出样例3:

-1

 代码呈上

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>//万能开头
using namespace std;
const int N=1010;
int n,m,k;
int ax,ay,bx,by;
char temp[N][N];
int dis[N][N];
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};//差不多DFS必备了吧
int main()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++)//行scanf("%s",temp[i]+1);//因为我们每一次列都是从第一个开始存的所以加一scanf("%d%d%d%d",&ax,&ay,&bx,&by);memset(dis,-1,sizeof dis);//先初始化将所有其所有定义为-1,有的是要定义无穷,要分题而论dis[ax][ay]=0;//用过的赋值为0if(ax==bx&&ay==by)//如果起点和终点完全符合,直接输出{cout<<0;return 0;}queue<pair<int,int>> g;//这个很牛,DFS都要用,相当于吧就是可以同时同个编号存多个数的数组g.push({ax,ay});//这可不是用scanf,这个直接扔进去push进行,是以列表存储的while(g.size())//根据是否有队头来当作循环条件{auto a=g.front();//取出队头g.pop();//相当于把队头弹出去for(int i=0;i<4;i++)//循环四个方向(上,下,左,右){for(int j=1;j<=k;j++)//这个题这里是1~k步要注意!{int x=a.first+j*dx[i],y=a.second+j*dy[i];//现在要判断的位置if(temp[x][y]=='#'||x<1||x>n||y<1||y>m)break;//第一层条件,如果是个陷阱,或者超出范围直接out!if(dis[x][y]!=-1&&dis[x][y]<=dis[a.first][a.second])break;//第二层条件,相当于剪枝,为了防止超时,如果本次的点之前已经到达过,//并且效果更好(走的步数更少),就直接out!因为其他这个点的四周肯定也是之前都判断过了if(dis[x][y]!=-1)continue;//第三层条件,要看题它是不影响的(注意:注意区分本题中移动次数与移动步数的区别。)g.push({x,y});//把这个点放入队头,如果多了也只会拿第一个dis[x][y]=dis[a.first][a.second]+1;//为什么每次都加1,其实它都是在起点的基础上,//并不是累加,在1~k都是一样的,为了防止在此期间就已经到达结尾if(x==bx&&y==by)//如果到达终点就输出次数{cout<<dis[x][y];return 0;}}}}puts("-1");// cout<<-1;return 0;
}

 

补充知识点:

auto的原理就是根据后面的值,来自己推测前面的类型是什么。

auto的作用就是为了简化变量初始化,如果这个变量有一个很长很长的初始化类型,就可以用auto代替。

错误原因:

1.本周还是要背一下DFS的板子,对于剪枝每次自己都想不到,就会tle,难啊难!

2.put("-1");笑不活了,还在想为啥为啥,突然想到没有一种可能是puts("-1"),这种可不敢出问题

3.今天看到了一个童鞋的博客说,y1与万能头(#include<bits/stdc++.h>)冲突,我没事,所以考试安安生生的多写点把/(ㄒoㄒ)/~~

欢迎来到一日一题的小菜鸟频道,睡不着就看看吧!

跟着小张刷题吧!
跟着小张刷题吧!

 

 

岩板材料