当前位置: 首页 > news >正文

【洛谷P9303题解】AC代码- [CCC 2023 J5] CCC Word Hunt

在CCC单词搜索游戏中,单词可以隐藏在字母网格中,以直线或直角的方式排列。以下是对代码的详细注释和解题思路的总结:

传送门: https://www.luogu.com.cn/problem/P9303

代码注释

#include <iostream>
#include <vector>
#include <string>using namespace std;// 定义八个可能的搜索方向
const int dx[8] = {-1,-1, 0, 1, 1, 1, 0,-1}; // 北、东北、东、东南、南、西南、西、西北
const int dy[8] = { 0, 1, 1, 1, 0,-1,-1,-1};int R, C; // 网格行数和列数
vector<string> grid; // 字母网格
string word; // 搜索区域分词
int word_len; // 单词长度// 检查坐标是否在网格范围内
bool inBounds(int x, int y) {return x >= 0 && x < R && y >= 0 && y < C;
}// 检查单词是否可以沿指定方向的直线排列
bool checkStraight(int x, int y, int dir) {for (int i = 0; i < word_len; ++i) {int nx = x + dx[dir] * i; // 计算下一个位置的行坐标int ny = y + dy[dir] * i; // 计算下一个位置的列坐标if (!inBounds(nx, ny) || grid[nx][ny] != word[i]) // 如果超出边界或字母不匹配return false; // 返回不匹配}return true; // 单词完全匹配
}// 检查单词是否可以以L形排列(直角)
bool checkLShape(int x, int y, int dir1, int dir2, int split) {// 检查第一段(从起点到分割点)for (int i = 0; i < split; ++i) {int nx = x + dx[dir1] * i;int ny = y + dy[dir1] * i;if (!inBounds(nx, ny) || grid[nx][ny] != word[i])return false;}// 从分割点开始,沿新的方向检查剩余部分int lx = x + dx[dir1] * (split - 1);int ly = y + dy[dir1] * (split - 1);for (int i = split; i < word_len; ++i) {lx += dx[dir2]; // 更新行坐标ly += dy[dir2]; // 更新列坐标if (!inBounds(lx, ly) || grid[lx][ly] != word[i])return false;}return true; // 单词完全匹配
}// 判断两个方向是否垂直
bool arePerpendicular(int dir1, int dir2) {return (dx[dir1] * dx[dir2] + dy[dir1] * dy[dir2]) == 0; // 点积为0则垂直
}int main() {cin >> word;word_len = word.length();cin >> R >> C;grid.resize(R);// 读取网格for (int i = 0; i < R; ++i) {grid[i] = "";for (int j = 0; j < C; ++j) {string ch;cin >> ch;grid[i] += ch;}}int count = 0;// 遍历每个单元格作为起点for (int x = 0; x < R; ++x) {for (int y = 0; y < C; ++y) {if (grid[x][y] != word[0]) continue; // 跳过不匹配首字母的单元格// 检查所有可能的直线排列for (int d = 0; d < 8; ++d) {if (checkStraight(x, y, d))count++;}// 检查所有可能的L形排列for (int d1 = 0; d1 < 8; ++d1) {for (int d2 = 0; d2 < 8; ++d2) {if (d1 == d2 || !arePerpendicular(d1, d2))continue; // 跳过相同方向或非垂直方向for (int split = 2; split < word_len; ++split) { // 分割点至少在第二个字母if (checkLShape(x, y, d1, d2, split))count++;}}}}}cout << count << endl; // 输出匹配次数return 0;
}

解题思路总结

  1. 输入读取:读取单词、网格的行数和列数,以及网格本身。
  2. 方向定义:定义八个可能的搜索方向,涵盖所有直线方向。
  3. 边界检查:确保坐标在网格范围内。
  4. 直线匹配:对于每个起点,检查是否可以沿八个方向之一形成直线排列。
  5. 直角匹配:对于每个起点,检查是否可以形成L形排列,确保两个方向垂直。
  6. 计数:统计所有可能的匹配方式,并输出总次数。

代码优点

  • 明确的方向定义:八个方向涵盖了所有可能的直线搜索方向。
  • 高效的边界检查:确保搜索过程中不越界。
  • 独立的匹配检查:直线和L形匹配的逻辑分离,代码结构清晰。
  • 垂直方向判断:通过点积判断两个方向是否垂直,数学上简洁有效。

代码缺点

  • 性能问题:对于较长的单词或较大的网格,递归搜索可能导致性能下降。
  • 重复计算:某些情况下可能会重复检查相同的路径。
  • 代码复杂度:涉及多个嵌套循环,可能影响可读性。

总结

该代码实现了对字母网格中单词的搜索,能够处理单词以直线或直角方式排列的情况。通过详细的注释和清晰的解题思路,代码易于理解和维护。

相关文章:

  • 如何合理选择智能外呼机器人:多维评估
  • PDF处理控件Aspose.PDF教程:压缩 PDF 文档的完整指南
  • ubuntu20.04安装CUDA、Cudnn
  • 【】20250527PDF文件拆分成多个pdf(两页一份,用幼儿班级姓名命名文件)
  • 速通《Sklearn 与 TensorFlow 机器学习实用指南》
  • [Windows] 视频配音:Krillin AI v1.1.4
  • 如何使用PHP创建一个安全的用户注册表单,包含输入验证、数据过滤和结果反馈教程。
  • Android Cameara2 + MediaRecorder 完成录像功能
  • 如何构建一个高效的 iOS 应用日志体系?从开发调试到使用KeyMob上线排查的实践经验
  • iOS QQ抽屉式导航的实现
  • Matlab实现LSTM-SVM时间序列预测,作者:机器学习之心
  • 循环神经网络(RNN):原理、架构与实战
  • 织梦dedecms arclist最新发布日期显示红色
  • 如何在 Windows 和 Mac 上擦拭和清洁希捷外置硬盘
  • 重新安装解决mac vscode点击不能跳转问题
  • Apache POI生成的pptx在office中打不开 兼容问题 wps中可以打卡问题 POI显示兼容问题
  • 智能手表单元测试报告(Unit Test Report)
  • 绝缘胶垫国标认证,10KV配电室专用5mm,迪宇电力10年生产厂家
  • 智能进化:拉马克式自体进化和达尔文式代际(版本)进化
  • [Java实战]Spring Boot切面编程实现日志记录(三十六)
  • 平顶山工程造价信息网/网站优化公司上海
  • 网站在线qq客服/今日头条seo
  • 网站建设问卷调研/郑州网络推广大包
  • 怎样做钓鱼网站/简述seo的基本步骤
  • 做医疗网站/唐山网站建设方案优化
  • 做网站建设的一般在哪儿找/狼雨的seo教程