题目描述
给定一个 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;//用过的赋值为0
if(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ㄒ)/~~
欢迎来到一日一题的小菜鸟频道,睡不着就看看吧!