进圈 | BFS

一、题目描述

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以文本方式显示
  1. 3 4 4↵
  2. ....↵
  3. .###↵
  4. ....↵
  5. 1 3 3 3↵
以文本方式显示
  1. 3↵
1秒64M0

二、思路过程

我觉得这题作为最后一题反而是五题里最简单的,前面四题做得死去活来的我如是说道。

很简单,同样是使用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及时止损,减少用时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值