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

【洛谷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形匹配的逻辑分离,代码结构清晰。
  • 垂直方向判断:通过点积判断两个方向是否垂直,数学上简洁有效。

代码缺点

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

总结

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

http://www.lryc.cn/news/2393432.html

相关文章:

  • NodeMediaEdge接入NodeMediaServer
  • 【Java基础-环境搭建-创建项目】IntelliJ IDEA创建Java项目的详细步骤
  • WebSocket指数避让与重连机制
  • DrissionPage WebPage模式:动态交互与高效爬取的完美平衡术
  • adb查看、设置cpu相关信息
  • PHP7+MySQL5.6 查立得源码授权系统DNS验证版
  • 68元开发板,开启智能硬件新篇章——明远智睿SSD2351深度解析
  • 【QQ音乐】sign签名| data参数加密 | AES-GCM加密 | webpack (下)
  • 基于netmiko模块实现支持SSH or Telnet的多线程多厂商网络设备自动化巡检脚本
  • 不用 apt 的解决方案(从源码手动安装 PortAudio)
  • 【前端】JS引擎 v.s. 正则表达式引擎
  • 开发体育平台,怎么接入最合适的数据接口
  • 3D虚拟工厂
  • http传输协议的加密
  • 半导体晶圆制造洁净厂房的微振控制方案-江苏泊苏系统集成有限公司
  • 嵌入式(1):STM32 GPIO与AFIO深度解析:从原理到高阶应用实战
  • Netty 实战篇:Netty RPC 框架整合 Spring Boot,迈向工程化
  • QML视图组件ListView、TableView、GridView介绍
  • 常见压缩算法性能和压缩率对比 LZ4 LZO ZSTD SNAPPY
  • Spring Boot 应用中实现配置文件敏感信息加密解密方案
  • 【TTS】基于GRPO的流匹配文本到语音改进:F5R-TTS
  • 动态规划-152.乘积最大子数组-力扣(LeetCode)
  • 1-1 初探Dart编程语言
  • 搭建最新版开源监控平台SigNoz踩的坑
  • Ubuntu 服务器配置与 Cloudflare Tunnel 部署指南 免费内网穿透家用服务器
  • 无人机多人协同控制技术解析
  • 【东枫科技】KrakenSDR 测向快速入门指南
  • 使用LangChain与多模态模型实现图像中的文字和表格提取(PDF可转图片)
  • 【Redis】hash
  • 基于Vite的前端自动化部署方案