news 2026/5/1 3:06:38

P11228 [CSP-J 2024] 地图探险

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P11228 [CSP-J 2024] 地图探险

记录51

#include<bits/stdc++.h> using namespace std; char mp[1010][1010]={}; int vis[1010][1010]={}; int dx[5]={0,1,0,-1}; int dy[5]={1,0,-1,0}; int main(){ int T,n,m,k,x,y,d; cin>>T; while(T--){ cin>>n>>m>>k; cin>>x>>y>>d; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) cin>>mp[i][j]; } int ans=1; vis[x][y]=1; //int cnt=1; while(k--){ //printf("第%d次操作:",cnt); int xn=x+dx[d]; int yn=y+dy[d]; if(xn>=1&&xn<=n&&yn>=1&yn<=m&&mp[xn][yn]=='.'){ if(vis[xn][yn]==0){ ans++; vis[xn][yn]=1; } x=xn; y=yn; //printf("走到(%d,%d) 第%d个位置\n",xn,yn,ans); } else{ d=++d%4; //printf("向%d方向转向\n",d); } //cnt++; } cout<<ans<<endl; memset(vis,0,sizeof(vis)); } return 0; }

题目传送门https://www.luogu.com.cn/problem/P11228


突破口

初始时,机器人的位置为 (x0​,y0​),朝向为 d0​。保证初始时机器人所在的位置为空地。接下来机器人将要进行 k 次操作。每一步,机器人将按照如下的模式操作

👉转向也算一次操作

保证字符串中只包含 x 和 . 两个字符。其中,第 x 行的字符串的第 y 个字符代表的位置为 (x,y)。这个位置是 x 即代表它是障碍,否则代表它是空地。数据保证机器人初始时所在的位置为空地。

👉有障碍物

地图上所有被机器人经过的位置(包括起始位置)有几个。

👉计算走的格子数,不重复计数


思路

并不是bfs跟dfs的题目,但是如果会搜索就很轻松做本题,这题纯模拟

  1. 构建地图
  2. 寻找可行路径
  3. 计数走过的格子

代码简析

#include<bits/stdc++.h> using namespace std; char mp[1010][1010]={}; int vis[1010][1010]={}; int dx[5]={0,1,0,-1}; int dy[5]={1,0,-1,0}; int main(){ int T,n,m,k,x,y,d; cin>>T; while(T--){ cin>>n>>m>>k; cin>>x>>y>>d; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) cin>>mp[i][j]; } } ... return 0; }

char mp[1010][1010]={};👉地图空间

int vis[1010][1010]={};👉判断地图上的点是否访问过,防止重复计数

int dx[5]={0,1,0,-1};👉x方向移动,上(减)下(加)移动

int dy[5]={1,0,-1,0};👉y方向移动,左(减)右(加)移动

注意:二者结合起来看,就是右下左上的逆时针转动

int T(几组数据),n(行数),m(列数),k(次数),x(停留的点),y(停留的点),d(转动方向);

#include<bits/stdc++.h> using namespace std; char mp[1010][1010]={}; int vis[1010][1010]={}; int dx[5]={0,1,0,-1}; int dy[5]={1,0,-1,0}; int main(){ int T,n,m,k,x,y,d; cin>>T; while(T--){ cin>>n>>m>>k; cin>>x>>y>>d; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) cin>>mp[i][j]; } int ans=1; vis[x][y]=1; //int cnt=1; while(k--){ //printf("第%d次操作:",cnt); int xn=x+dx[d]; int yn=y+dy[d]; if(xn>=1&&xn<=n&&yn>=1&yn<=m&&mp[xn][yn]=='.'){ if(vis[xn][yn]==0){ ans++; vis[xn][yn]=1; } x=xn; y=yn; //printf("走到(%d,%d) 第%d个位置\n",xn,yn,ans); } else{ d=++d%4; //printf("向%d方向转向\n",d); } //cnt++; } cout<<ans<<endl; memset(vis,0,sizeof(vis)); } return 0; }

int ans=1;👉起点是经过的第一个格子

vis[x][y]=1;👉地图上记录起点访问过

while(k--){}👉只执行k次操作

int xn=x+dx[d]; int yn=y+dy[d];👉记录接下来移动后的位置

if(xn>=1&&xn<=n&&yn>=1&yn<=m&&mp[xn][yn]=='.'){}👉判断路径是否可行

ans++; vis[xn][yn]=1;👉格子数加1,同时记录这个点经过了

x=xn; y=yn;👉更新停留的点

else{d=++d%4;}👉路径不可行的时候进行转向

cout<<ans<<endl;👉输出经过的点

memset(vis,0,sizeof(vis));👉访问数组重置,防止下一组数据被污染


补充

CSP-J DFS/BFS 技巧完全汇总


一、搜索题识别特征(先判断用哪个)

特征DFS(深度优先)BFS(广度优先)
目标路径方案数连通块最短路径/步数最小操作
数据结构图、树、网格图、网格
关键词"有多少种方案"、"路径"、"连通""最少步数"、"最短"、"最快"
典型题迷宫路径数、连通块、选物品迷宫最短路径、倒水问题、编辑距离
CSP-J频率★★★★★★★★★★

二、DFS核心技巧(CSP-J必背)

技巧1:记忆化搜索(DP化)

场景:重复子问题,如迷宫路径数

int dfs(int x, int y) { if (x == n && y == m) return 1; if (vis[x][y]) return dp[x][y]; // 记忆化 vis[x][y] = true; int ans = 0; for (int dir = 0; dir < 4; dir++) { int nx = x + dx[dir], ny = y + dy[dir]; if (valid(nx, ny)) { ans += dfs(nx, ny); } } return dp[x][y] = ans; // 保存结果 }

作用:将O(4ⁿ)降到O(n²)


技巧2:连通块标记(最常用)

场景:统计岛屿数量、洪水填充

void dfs(int x, int y) { if (x<1 || x>n || y<1 || y>m || a[x][y]!=1) return; // 边界 a[x][y] = 2; // 标记为已访问 for (int dir=0; dir<4; dir++) { dfs(x+dx[dir], y+dy[dir]); } } // 统计连通块 int cnt = 0; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (a[i][j] == 1) { dfs(i, j); cnt++; }

技巧3:选物品/组合(回溯+剪枝)

场景:从n个物品选k个,和为目标值

bool dfs(int idx, int sum, int chosen) { if (chosen == k && sum == target) return true; if (idx > n || chosen > k || sum > target) return false; // 剪枝 // 选当前 if (dfs(idx+1, sum+a[idx], chosen+1)) return true; // 不选当前 if (dfs(idx+1, sum, chosen)) return true; return false; }

技巧4:树形DFS(树遍历)

场景:树的深度、子树大小、路径和

int depth[N]; void dfs(int u, int parent) { for (int v : g[u]) { if (v == parent) continue; // 避免回父节点 depth[v] = depth[u] + 1; dfs(v, u); } }

三、BFS核心技巧(CSP-J必背)

技巧1:最短路径(最核心)

场景:迷宫最短步数、最少操作

int bfs(int sx, int sy) { queue<pair<int, int>> q; q.push({sx, sy}); vis[sx][sy] = 0; // 距离数组 while (!q.empty()) { auto [x, y] = q.front(); q.pop(); if (x == tx && y == ty) return vis[x][y]; for (int dir=0; dir<4; dir++) { int nx = x + dx[dir], ny = y + dy[dir]; if (valid(nx, ny) && !vis[nx][ny]) { vis[nx][ny] = vis[x][y] + 1; q.push({nx, ny}); } } } return -1; // 无法到达 }

记忆:BFS第一次到达终点时,步数一定是最短的


技巧2:多源BFS(洪水填充优化)

场景:多个起点同时扩展

// 将所有起点同时入队 queue<pair<int, int>> q; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (a[i][j] == 起点) { q.push({i, j}); vis[i][j] = 0; } // BFS扩展,谁先到终点谁最短 while (!q.empty()) { ... }

技巧3:0-1 BFS(边权为0或1)

场景:某些方向代价为0,某些为1(如转向代价)

deque<pair<int, int>> q; // 用双端队列 vis[sx][sy] = 0; q.push_front({sx, sy}); // 起点从队首入 while (!q.empty()) { auto [x, y] = q.front(); q.pop_front(); for (int dir=0; dir<4; dir++) { int nx = x + dx[dir], ny = y + dy[dir]; int w = (dir == 方向) ? 0 : 1; // 代价 if (valid(nx, ny) && vis[x][y] + w < vis[nx][ny]) { vis[nx][ny] = vis[x][y] + w; if (w == 0) q.push_front({nx, ny}); else q.push_back({nx, ny}); } } }

四、DFS vs BFS 选择决策树

是否需要求最短/最少? ├── 是 → BFS(第一次到终点即最短) │ └── 边权为0/1 → 0-1 BFS/双端队列 │ └── 否 → DFS(找路径、方案数、连通块) ├── 有重复子问题 → 记忆化搜索 ├── 找所有方案 → 回溯+剪枝 └── 只需遍历 → 普通DFS

五、CSP-J搜索题通用模板

DFS模板(连通块)

const int N = 1010; int n, m, a[N][N]; bool vis[N][N]; int dx[] = {-1, 1, 0, 0}; int dy[] = {0, 0, -1, 1}; void dfs(int x, int y) { if (x<1 || x>n || y<1 || y>m || a[x][y]==0 || vis[x][y]) return; vis[x][y] = true; for (int dir=0; dir<4; dir++) { dfs(x+dx[dir], y+dy[dir]); } }

BFS模板(最短路径)

int bfs(int sx, int sy, int tx, int ty) { memset(vis, -1, sizeof(vis)); queue<pair<int, int>> q; q.push({sx, sy}); vis[sx][sy] = 0; while (!q.empty()) { auto [x, y] = q.front(); q.pop(); if (x == tx && y == ty) return vis[x][y]; for (int dir=0; dir<4; dir++) { int nx = x + dx[dir], ny = y + dy[dir]; if (nx>=1 && nx<=n && ny>=1 && ny<=m && a[nx][ny]==1 && vis[nx][ny]==-1) { vis[nx][ny] = vis[x][y] + 1; q.push({nx, ny}); } } } return -1; // 无法到达 }

六、性能优化技巧

1. 剪枝(Pruning)

if (当前步数 >= 最优解) return; // 步数剪枝 if (当前和 > 目标值) return; // 和剪枝 if (不可能到达) return; // 可行性剪枝

2. 迭代加深(DFS深度限制)

for (int depth = 1; depth <= MAX_DEPTH; depth++) { if (dfs(起点, depth)) { // 限制深度搜索 cout << depth; // 找到最优解 break; } }

3. 双向BFS

// 从起点和终点同时开始BFS,在中间相遇 queue<pair<int, int>> q1, q2; // 交替扩展,直到相遇

七、调试与容错技巧

1. 访问越界检查

#define valid(x, y) (x>=1 && x<=n && y>=1 && y<=m && !vis[x][y]) // 或函数形式 inline bool check(int x, int y) { return x>=1 && x<=n && y>=1 && y<=m && a[x][y]==1; }

2. 递归深度限制

// DFS递归深度超过10^5会栈溢出,改用栈模拟迭代 if (depth > 100000) return false; // 提前退出

3. BFS队列大小

// 最坏情况队列大小 = n×m,开数组要开够 queue<pair<int, int>> q; // 或用数组模拟队列

八、CSP-J高频搜索题清单

年份题目搜索类型难度
2023 T1小苹果流程模拟(类BFS)★☆☆☆☆
2022 T1乘方DFS(递归)★☆☆☆☆
2021迷宫BFS最短路径★★☆☆☆
2020连通块DFS染色★★☆☆☆
2019选物品DFS回溯★★☆☆☆

九、一句话总结

CSP-J搜索题 = 先判BFS/DFS → 写模板 → 加剪枝 → 防越界 → 调试输出,BFS找最短,DFS找路径,记忆化防超时,全局开大数组。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 3:03:10

5分钟掌握Git Auto Commit Action:自动化提交的终极指南

5分钟掌握Git Auto Commit Action&#xff1a;自动化提交的终极指南 【免费下载链接】git-auto-commit-action Automatically commit and push changed files back to GitHub with this GitHub Action for the 80% use case. 项目地址: https://gitcode.com/gh_mirrors/gi/gi…

作者头像 李华
网站建设 2026/4/29 18:35:15

23、深入解析Samba、Active Directory与Kerberos的安全机制

深入解析Samba、Active Directory与Kerberos的安全机制 1. 任务背景与Samba的选择考量 在企业网络环境中,常常会面临各种复杂的安全和技术问题。就像Bob认同了Stan的建议,聘请专业服务来解决潜在的危机一样,我们也需要对相关技术进行深入分析和决策。 Samba - 3是一款可自…

作者头像 李华
网站建设 2026/4/24 7:44:18

29、软件开发及网络技术相关知识整合

软件开发及网络技术相关知识整合 在软件开发领域,若开发者期望新程序对公众发挥最大效用,将其打造成自由软件是上佳之选。以下为你详细介绍如何将此理念应用于新程序,以及相关网络技术的关键要点。 一、开发自由软件的操作步骤 若你开发新程序并希望它成为自由软件,需按…

作者头像 李华
网站建设 2026/4/26 22:57:46

PHP程序员正能量自我实现预言的知识体系

太棒了&#xff0c;这个问题直指个人成长的最高杠杆点——“自我实现预言”。对PHP程序员而言&#xff0c;这不是玄学&#xff0c;而是一套通过有意识地塑造内在信念与叙事&#xff0c;从而系统性改变外在行为、决策和结果的心理工程学。一、核心原理&#xff1a;预言如何“自我…

作者头像 李华
网站建设 2026/4/29 16:31:50

arXiv LaTeX Cleaner 完整使用指南:保护隐私与优化论文提交

arXiv LaTeX Cleaner 完整使用指南&#xff1a;保护隐私与优化论文提交 【免费下载链接】arxiv-latex-cleaner arXiv LaTeX Cleaner: Easily clean the LaTeX code of your paper to submit to arXiv 项目地址: https://gitcode.com/gh_mirrors/ar/arxiv-latex-cleaner …

作者头像 李华
网站建设 2026/4/29 20:20:53

RuoYi-Vue Pro 企业级管理系统:从零到一的完整部署指南

RuoYi-Vue Pro 企业级管理系统&#xff1a;从零到一的完整部署指南 【免费下载链接】ruoyi-vue-pro &#x1f525; 官方推荐 &#x1f525; RuoYi-Vue 全新 Pro 版本&#xff0c;优化重构所有功能。基于 Spring Boot MyBatis Plus Vue & Element 实现的后台管理系统 微信…

作者头像 李华