CSP-J 2024 T2 地图探险【题解】

CSP-J 2024 T2 地图探险

题目大意

有一片丛林,其环境可以用一个二维数组表示:

  • .代表此地为空地,可走。
  • x代表此地非空地,不可走。

有一个机器人探路,他的状态分为两个值:

  • 位置。
  • 方向。

机器人探路有这样一些规则:

  • 若前方有路,直接往前走(不管是否走过)。
  • 遇到障碍物,右转。

现在给出机器人的初始状态(一定在空地),求执行k次操作之后,机器人经过了多少地方(右转算一次操作,前进算一次操作)。

思路

需要的变量 / 数组

描述机器人状态需要的3个变量:

  • x:位置。
  • y:位置。
  • d:朝向(0~3)。

vis数组:

  • 当机器人走过[x, y],vis[x][y] = true

dir数组:

  • dir[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0}}
  • [x + dir[d][0], y + dir[d][1]]表示当机器人朝向为d时往前走一步之后的位置。
  • d = 0: 右 (0, 1)。
  • d = 1: 下 (1, 0)。
  • d = 2: 左 (0, -1)。
  • d = 3: 上 (-1, 0)。

核心思想

vis[x][y] = true;
while (k--) {
   
   
    int nx = x + dir[d][0], ny = y + dir[d][1]; // 计算下一步的位置
    if (!(nx >= 1 && nx <= n && ny >= 1 && ny <= m && mp
### 题目信息 丛林的地图可以用一个 n 行 m 列的字符表来表示。第 i 行第 j 列的位置的坐标记作(i, j),其中 1 ≤ i ≤ n,1 ≤ j ≤ m。如果某个位置的字符为“x”,则代表该位置上有障碍,不可通过;如果某个位置的字符为“.”,则代表该位置是一片空地,可以通过 [^1]。 ### 解题思路 #### BFS 思路 BFS 执行过程是从队列取出元素,对其四个方向进行遍历,对于新位置进行越界、障碍物和已访问检查,若不符合则跳过,若符合则更新距离,若到达终点则返回结果,否则将新位置加入队列 [^2]。 ```cpp while(!q.empty()){ auto [x,y] = q.front(); q.pop(); for(方向遍历){ int nx = x+dx, ny = y+dy; if(越界检查 || 障碍物检查 || 已访问检查) continue; dist[nx][ny] = dist[x][y]+1; if(到达终点) return 结果; q.push({nx,ny}); } } ``` #### 另一种思路(代码思路) 1. 读取输入的测试用例数 T,对于每个测试用例,读取地图的行数 n、列数 m 和步数 k,以及起始位置 (x, y) 和初始方向 d。 2. 初始化访问数组 vis 为 0,读取地图信息存储在字符数组 a 中,将起始位置标记为已访问。 3. 进行 k 步移动,对于每一步,根据当前方向计算下一个位置,如果该位置合法且为空地,则移动到该位置并标记为已访问;否则右转。 4. 统计访问数组中已访问的位置数量并输出。 ### 代码答案 ```cpp #include<iostream> #include<cstring> using namespace std; #define MaxN 1005 #define For(i, j, k) for(int i = j; i <= k; i++) int dx[] = {0, 1, 0, -1}; int dy[] = {1, 0, -1, 0}; int vis[MaxN][MaxN]; char a[MaxN][MaxN]; int T, n, m, k; int x, y, d; //对应题目中的x0,y0,d0 //注意这里最好不要用x0y0,因为万能头中y0,y1已经被定义过,容易重定义 int main() { cin >> T; while (T--){ cin >> n >> m >> k; cin >> x >> y >> d; memset(vis, 0, sizeof(vis)); //初始化 For(i, 1, n){ For(j, 1, m){ cin >> a[i][j]; } } vis[x][y] = 1; // 开始位置也计算在内 For(i, 1, k){ int nx = x+dx[d], ny = y+dy[d]; //当前位置 if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] == '.'){ //能走 x = nx, y = ny; vis[nx][ny] = 1; // cout << nx << ' ' << ny << endl; } else d = (d+1) % 4; //右转 } //统计数量 int ans = 0; For(i, 1, n){ For(j, 1, m){ if (vis[i][j]) ans++; } } cout << ans << endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值