目录
题目
小明在玩连连看游戏,目标是消除相同的数字,游戏规定:
- 两个位置必须数字相同才能消除
- 连接路径只能经过空格
- 连接路径最多只能有两次拐弯
- 连接线路可以走地图的边界
- 消除后位置变为空格("")
第一行输入一个数组代表连连看的地图矩阵,形式类似于: [[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
// 方向数组:上下左右
const DIRECTION_X = [-1, 1, 0, 0];
const DIRECTION_Y = [0, 0, -1, 1];
// 解析地图字符串
function processGameMap(inputStr) {
// 移除外层括号
inputStr = inputStr.slice(2, -2);
const rows = inputStr.split('],[');
// 创建初始地图
const gameMap = rows.map(row => row.split(','));
// 获取尺寸
const rowCnt = gameMap.length;
const colCnt = gameMap[0].length;
// 创建带边界的新地图
const borderedMap = Array(rowCnt + 2).fill().map(() =>
Array(colCnt + 2).fill(' '));
// 填充数据
for (let i = 0; i < rowCnt; i++) {
for (let j = 0; j < colCnt; j++) {
borderedMap[i + 1][j + 1] = gameMap[i][j];
}
}
return borderedMap;
}
// DFS搜索路径
function explorePath(board, currX, currY, targetX, targetY, currDir, turns, visited, minTurns) {
const rowCnt = board.length;
const colCnt = board[0].length;
const posIdx = currX * colCnt + currY;
// 剪枝条件
if (currDir !== -1 && turns >= minTurns[posIdx][currDir]) return false;
if (turns > 2) return false;
// 更新最小拐弯数
if (currDir !== -1) minTurns[posIdx][currDir] = turns;
// 到达目标
if (currX === targetX && currY === targetY) return true;
// 探索四个方向
for (let nextDir = 0; nextDir < 4; nextDir++) {
const nextX = currX + DIRECTION_X[nextDir];
const nextY = currY + DIRECTION_Y[nextDir];
// 边界检查
if (nextX < 0 || nextX >= rowCnt || nextY < 0 || nextY >= colCnt) continue;
// 访问检查
const key = `${nextX},${nextY}`;
if (visited.has(key)) continue;
// 路径检查
if (!(nextX === targetX && nextY === targetY) && board[nextX][nextY] !== ' ') continue;
// 计算拐弯
const nextTurns = turns + (currDir !== -1 && currDir !== nextDir ? 1 : 0);
// 记录访问
visited.add(key);
if (explorePath(board, nextX, nextY, targetX, targetY,
nextDir, nextTurns, visited, minTurns)) {
return true;
}
visited.delete(key);
}
return false;
}
// 检查连接
function verifyConnection(board, x1, y1, x2, y2) {
if (board[x1][y1] !== board[x2][y2]) return false;
if (x1 === x2 && y1 === y2) return false;
const rowCnt = board.length;
const colCnt = board[0].length;
// 初始化最小拐弯数数组
const minTurns = Array(rowCnt * colCnt).fill().map(() =>
Array(4).fill(Infinity));
// 初始化访问集合
const visited = new Set([`${x1},${y1}`]);
if (explorePath(board, x1, y1, x2, y2, -1, 0, visited, minTurns)) {
board[x1][y1] = ' ';
board[x2][y2] = ' ';
return true;
}
return false;
}
// 主函数
function main(input) {
const lines = input.trim().split('\n');
const gameBoard = processGameMap(lines[0]);
const operationCount = parseInt(lines[1]);
for (let i = 0; i < operationCount; i++) {
const [y1, x1, y2, x2] = lines[i + 2].split(' ').map(x => parseInt(x) + 1);
if (!verifyConnection(gameBoard, x1, y1, x2, y2)) {
console.log("NO");
return;
}
}
console.log("OK");
}
// 处理输入(Node.js环境)
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let inputString = '';
process.stdin.on('data', inputStdin => {
inputString += inputStdin;
});
process.stdin.on('end', () => {
main(inputString);
});
【华为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。让他帮助你查询原因。