一、题目描述
Description
龙龙最近迷上了一款名叫 PUBG(PLAYERUNKNOWN’S BATTLEGROUNDS)的手游,那是一款关乎生存挑战的 RPG 逃亡游戏。考虑到游戏的环节过于复杂,龙龙决定简化一下场景:整个地图可以看做一个长为 n 宽为 m 的二维格点平面。龙龙需要从(x1,y1)逃亡到(x2,y2)以逃离毒圈,但有些格点上存在障碍 # 不能行走,有些格点是沙地 . 。龙龙只能移动在允许行走的沙地上,同时每一时刻,龙龙只能朝着当前位置周围的上、下、左、右四个方向移动。同时因为龙龙使用了能量饮料,每分钟最多可以朝着一个方向行走 k 步。
毒圈快要来啦,请你帮龙龙尽快安排一下可行的路线,使得它能够以最短的时间顺利进圈。
Input
第一行输入三个正整数 n,m 和 k(1 ≤ n,m,k ≤ 1000),表示地图的大小还有龙龙每分钟最多可以移动的步数;接下来 n 行,每行包含 m 个字符,其中第 i 行第 j 个字符表示坐标(i,j)的路况,它可能是 # ,这表示这个格点是障碍区,不能行走,也可能是 . ,这表示沙地;
最后一行输入四个正整数 x1,y1,x2,y2,由空格间隔开,表示龙龙的初始位置和目标位置。
Output
请输出一个正整数 t,表示龙龙从(x1,y1)到(x2,y2)进圈最少需要的时间(分钟),如果龙龙最终不能进圈,则请输出-1。
测试输入 期待的输出 时间限制 内存限制 额外进程 测试用例 1 以文本方式显示
- 3 4 4↵
- ....↵
- .###↵
- ....↵
- 1 3 3 3↵
以文本方式显示
- 3↵
1秒 64M 0
二、思路过程
我觉得这题作为最后一题反而是五题里最简单的,前面四题做得死去活来的我如是说道。
很简单,同样是使用BFS,速度快而且不会出错。
手动随便搞了个例子,假设S是起点,E是终点,只要给每一个点都打上层数就行了。
所以上面的例子答案就是7。
关于BFS的写法,在成语接龙那里面写过了,不再赘述。
以上为思路,代码正在写,目测不难。
9.4号更新完整代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int n,m,k;
int sx,sy,ex,ey; //开始和结束的x、y坐标
char tr[N][N];
int step[N][N]; //层数
bool vis[N][N];
void bfs() {
queue<pair<int,int>> q;
//从起点开始
vis[sx][sy] = true;
step[sx][sy] = 0;
q.push(make_pair(sx,sy));
while ( q.size() ) {
auto cur = q.front();
q.pop();
//向上走
for (int up_i=1;up_i<=k;up_i++) {
if ( (cur.first-up_i>=1) && (tr[cur.first-up_i][cur.second]=='.') ) {
if (!vis[cur.first-up_i][cur.second]) {
vis[cur.first-up_i][cur.second] = true;
step[cur.first-up_i][cur.second] = step[cur.first][cur.second] + 1;
q.push(make_pair(cur.first-up_i,cur.second));
}
else continue;
}
else break;
}
//向下走
for (int down_i=1;down_i<=k;down_i++) {
if ( (cur.first+down_i<=n) && (tr[cur.first+down_i][cur.second]=='.') ) {
if ( !vis[cur.first+down_i][cur.second] ) {
vis[cur.first+down_i][cur.second] = true;
step[cur.first+down_i][cur.second] = step[cur.first][cur.second] + 1;
q.push(make_pair(cur.first+down_i,cur.second));
}
else continue;
}
else break;
}
//向左走
for (int left_i=1;left_i<=k;left_i++) {
if ( (cur.second-left_i>=1) && (tr[cur.first][cur.second-left_i]=='.') ) {
if ( !vis[cur.first][cur.second-left_i] ) {
vis[cur.first][cur.second-left_i] = true;
step[cur.first][cur.second-left_i] = step[cur.first][cur.second] + 1;
q.push(make_pair(cur.first,cur.second-left_i));
}
else continue;
}
else break;
}
//向右走
for (int right_i=1;right_i<=k;right_i++) {
if ( (cur.second+right_i<=m) && (tr[cur.first][cur.second+right_i]=='.') ) {
if ( !vis[cur.first][cur.second+right_i] ) {
vis[cur.first][cur.second+right_i] = true;
step[cur.first][cur.second+right_i] = step[cur.first][cur.second] + 1;
q.push(make_pair(cur.first,cur.second+right_i));
}
else continue;
}
else break;
}
if (step[ex][ey]!=-1) goto p;
}
p: ;
}
int main(){
void bfs();
memset(step,-1,sizeof(step));
memset(vis,false,sizeof(vis));
scanf("%d %d %d",&n,&m,&k);
for (int i=1;i<=n;i++) {
getchar();
for (int j=1;j<=m;j++) {
tr[i][j] = getchar();
}
}
scanf("%d %d %d %d",&sx,&sy,&ex,&ey);
bfs();
cout << step[ex][ey] << endl;
return 0;
}
注意两个要点,第一,如果遇到vis为true不能直接break,而应该使用continue;第二,continue可能会导致TLE,故使用goto及时止损,减少用时。