2025华为od机试真题B卷【连连看游戏】C++实现

目录

题目

思路

Code


题目

小明在玩连连看游戏,目标是消除相同的数字,游戏规定:

  • 两个位置必须数字相同才能消除
  • 连接路径只能经过空格
  • 连接路径最多只能有两次拐弯
  • 连接线路可以走地图的边界
  • 消除后位置变为空格("")

第一行输入一个数组代表连连看的地图矩阵,形式类似于: [[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。让他帮助你查询原因。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MISAYAONE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值