目录
题目
小明在玩连连看游戏,目标是消除相同的数字,游戏规定:
- 两个位置必须数字相同才能消除
- 连接路径只能经过空格
- 连接路径最多只能有两次拐弯
- 连接线路可以走地图的边界
- 消除后位置变为空格("")
第一行输入一个数组代表连连看的地图矩阵,形式类似于: [[4,5,4] [5,4,5]] ,第一行输入n,表示操作步骤数,接下来r行,每行输入四个数字 y1 x1 y2 x2 代表此次操作的两个位置。题目要求判断按照操作步骤执行,是否每一步都能进行消除,可以的话输出 OK,否则输出 NO。
输入描述
第一行输入 一个字符串,代表 连连看的地图。
第二行输出一个 n,代表操作步骤数
接下来的n行,每一行输入y1 x1 y2 x2 代表此次操作的两个表格位置
备注
不必考虑输入不合法的情况
输出描述
输入步骤能全部正常消除则输出 OK 。否则输出 NO示例1:
输入:
[[4,5,4],[5,4,5]]
2
0 0 2 0
1 0 0 1输出:
OK
说明:
位置(0,0)到位置(0,2)上,都是4,可以消除
位置(0,1)到位置(1,0)上,都是5,可以消除
思路
解题思路
地图预处理
- 解析输入字符串为二维数组
- 添加边界,使用空格填充
- 便于处理边界情况
路径搜索策略
- 使用DFS深度优先搜索
- 记录已访问位置避免循环
- 记录每个位置的最小拐弯数进行剪枝
- 四个方向搜索:上、下、左、右
关键优化点
- 使用位置索引优化访问记录
- 方向编码优化拐弯判断
- 提前剪枝减少搜索空间
Code
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <sstream>
#include <climits>
using namespace std;
// 方向数组:上下左右
const int direction_x[] = {-1, 1, 0, 0};
const int direction_y[] = {0, 0, -1, 1};
// 解析地图字符串为二维数组
vector<vector<string>> process_game_map(string input_str) {
// 移除外层括号
input_str = input_str.substr(2, input_str.length() - 4);
vector<string> rows;
string current_row;
size_t pos = 0;
// 分割行
while ((pos = input_str.find("],[")) != string::npos) {
current_row = input_str.substr(0, pos);
rows.push_back(current_row);
input_str.erase(0, pos + 3);
}
rows.push_back(input_str);
// 处理每行数据
vector<vector<string>> game_map;
for (const string& row : rows) {
vector<string> cells;
stringstream ss(row);
string cell;
while (getline(ss, cell, ',')) {
cells.push_back(cell);
}
game_map.push_back(cells);
}
// 添加边界
int row_cnt = game_map.size();
int col_cnt = game_map[0].size();
vector<vector<string>> bordered_map(row_cnt + 2, vector<string>(col_cnt + 2, " "));
for (int i = 0; i < row_cnt; i++) {
for (int j = 0; j < col_cnt; j++) {
bordered_map[i + 1][j + 1] = game_map[i][j];
}
}
return bordered_map;
}
// DFS搜索路径
bool explore_path(vector<vector<string>>& board,
int curr_x, int curr_y,
int target_x, int target_y,
int curr_dir, int turns,
set<pair<int, int>>& visited,
vector<vector<int>>& min_turns) {
int row_cnt = board.size();
int col_cnt = board[0].size();
int pos_idx = curr_x * col_cnt + curr_y;
// 剪枝:拐弯次数检查
if (curr_dir != -1 && turns >= min_turns[pos_idx][curr_dir]) return false;
if (turns > 2) return false;
// 更新最小拐弯数
if (curr_dir != -1) min_turns[pos_idx][curr_dir] = turns;
// 到达目标
if (curr_x == target_x && curr_y == target_y) return true;
// 探索四个方向
for (int next_dir = 0; next_dir < 4; next_dir++) {
int next_x = curr_x + direction_x[next_dir];
int next_y = curr_y + direction_y[next_dir];
// 边界检查
if (next_x < 0 || next_x >= row_cnt || next_y < 0 || next_y >= col_cnt) continue;
// 访问检查
if (visited.count({next_x, next_y})) continue;
// 路径检查
if (!(next_x == target_x && next_y == target_y) && board[next_x][next_y] != " ") continue;
// 计算拐弯
int next_turns = turns + (curr_dir != -1 && curr_dir != next_dir ? 1 : 0);
// 记录访问
visited.insert({next_x, next_y});
if (explore_path(board, next_x, next_y, target_x, target_y,
next_dir, next_turns, visited, min_turns)) {
return true;
}
visited.erase({next_x, next_y});
}
return false;
}
// 检查两点是否可以连接
bool verify_connection(vector<vector<string>>& board, int x1, int y1, int x2, int y2) {
if (board[x1][y1] != board[x2][y2]) return false;
if (x1 == x2 && y1 == y2) return false;
int row_cnt = board.size();
int col_cnt = board[0].size();
vector<vector<int>> min_turns(row_cnt * col_cnt, vector<int>(4, INT_MAX));
set<pair<int, int>> visited{{x1, y1}};
if (explore_path(board, x1, y1, x2, y2, -1, 0, visited, min_turns)) {
board[x1][y1] = " ";
board[x2][y2] = " ";
return true;
}
return false;
}
int main() {
string input_str;
getline(cin, input_str);
int operation_count;
cin >> operation_count;
auto game_board = process_game_map(input_str);
for (int i = 0; i < operation_count; i++) {
int y1, x1, y2, x2;
cin >> y1 >> x1 >> y2 >> x2;
x1++; y1++; x2++; y2++;
if (!verify_connection(game_board, x1, y1, x2, y2)) {
cout << "NO" << endl;
return 0;
}
}
cout << "OK" << endl;
return 0;
}
【华为od机试真题Python+JS+Java合集】【超值优惠】:Py/JS/Java合集
【华为od机试真题Python】:Python真题题库
【华为od机试真题JavaScript】:JavaScript真题题库
【华为od机试真题Java】:Java真题题库
【华为od机试真题C++】:C++真题题库
【华为od机试真题C语言】:C语言真题题库
【华为od面试手撕代码题库】:面试手撕代码题库
【华为od机试面试交流群:830285880】
华为OD机试:二本院校有机会吗?
有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。


1101

被折叠的 条评论
为什么被折叠?



