题目部分
题目 | 机器人活动区域 |
难度 | 难 |
题目说明 | 有一个机器人,可放置于 M x N 的网格中任意位置,每个网格包含一个非负整数编号,当相邻网格的数字编号差值的绝对值小于等于 1 时,机器人可以在网格间移动。 求机器人可活动的最大范围对应的网络点数目。 说明:机器人之鞥你在相邻网格间上、下、左、右移动。 示例,输入如下网格: 输出:6 说明:图中绿色区域,相邻网格差值的绝对值小于或等于 1,且为最大区域,对应的网格个数为 6。 示例 2,输入以下网格: 输出:1 说明:任意两个相邻网格之差的绝对值都大于 1,机器人不能在网格间移动,只能在单个网格内活动,对应网格个数为 1。 |
输入描述 | 第一行输入 M 和 N。M 表示网格的行数,N 表示网格的列数。 之后的 M 行表示网格的数值,每个 N 个数值(假设数值为 k),数值间用单个空格间隔,行首和行尾无多余的空格。 M、N、k 均为整数,且 1 <= M, N <= 150,0 <= k <= 50。 |
输出描述 | 输出 1 行,包含 1 个数字,表示最大活动区域对应的网格个数。 |
补充说明 | 假设输入个数和输入数据全部合法。 |
------------------------------------------------------ | |
示例 | |
示例1 | |
输入 | 4 4 1 2 5 2 2 4 4 5 3 5 7 1 4 6 2 4 |
输出 | 6 |
说明 | 见描述中示例 1,最大区域对应的网格个数为 6。 |
示例2 | |
输入 | 2 3 1 3 5 4 1 3 |
输出 | 1 |
说明 | 任意两个相邻网格之差的绝对值都大于 1,机器人无法移动,最大区域对应网格点个数为 1。 |
解读与分析
题目解读:
此题要求从一个二维的网格中,找出 1 到多个区域,确保每个区域中相邻格子的数字之差不大于 1。
分析与思路:
在 Windows 95 上,有一款经典的扫雷游戏,点下一个方块,如果这个方块不是地雷,就会显示它周围(8个方向)的地雷总数,如果它附近没有地雷,那么周围 8 个方向的方块也会自动点开,如果这 8 个方向的方块……。
在算法上,此题与扫雷算法类似。
可以从网格中的一个格子开始,采用遍历的方式(深度遍历或广度遍历都可以),获取与它相邻的所有数字之差不大于 1 的格子,直到找到所有符合条件的格子,或整个网格中所有的格子都已经遍历完毕,此时,就找到了一个符合条件的区域。
接下来,从网格中找到下一个(没有遍历过)不在任何区域中的点,以这个点为始点,继续遍历,寻找与它相邻数字不大于 1 的格子,直到找到第二个区域。
按照相同的方法,找到所有的区域。最后,找出格子最多的区域,输出其格子数。
需要注意:使用的格子,在下次判断的时候,不应重复统计。
代码实现
Java代码
import java.util.Scanner;
/**
* 机器人活动区域
* @since 2023.09.26
* @version 0.1
* @author Frank
*
*/
public class RobotMoveArea {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
// 第一行输入一串数字,以空格分隔
String line = sc.nextLine();
String[] rec = line.split(" ");
int rowCnt = Integer.parseInt( rec[0] );
int columnCnt = Integer.parseInt( rec[1] );
int[][] area = new int[rowCnt][columnCnt];
for( int i = 0; i < rowCnt; i ++ )
{
String row = sc.nextLine();
String[] columns = row.split(" ");
for( int j = 0; j < columnCnt; j ++ )
{
area[i][j] = Integer.parseInt( columns[j] );
}
}
processRobotMoveArea( area);
}
}
private static void processRobotMoveArea( int[][] area ) {
int maxPartAreaCnt = 0;
for( int i = 0; i < area.length; i ++ )
{
for( int j = 0; j < area[i].length; j ++ )
{
int cellValue = area[i][j];
if( cellValue == -1 )
{
continue;
}
int partAreaCnt = getPartAraCnt( i, j , area );
if( partAreaCnt > maxPartAreaCnt )
{
maxPartAreaCnt = partAreaCnt;
}
}
}
System.out.println( maxPartAreaCnt );
}
private static int getPartAraCnt( int i, int j, int[][] area ) {
int areaCnt = 0;
int rowCnt = area.length;
int columnCnt = area[0].length;
int cellValue = area[i][j];
area[i][j] = -1;
areaCnt ++;
if( i > 0 && area[i - 1][j] != -1 && Math.abs(cellValue - area[i - 1][j]) <= 1 )
{
areaCnt += getPartAraCnt( i - 1, j, area );
}
if( i < rowCnt - 1 && area[i + 1][j] != -1 && Math.abs(cellValue - area[i + 1][j]) <= 1)
{
areaCnt += getPartAraCnt( i + 1, j, area );
}
if( j > 0 && area[i][j - 1 ] != -1 && Math.abs(cellValue - area[i][j-1]) <= 1) {
areaCnt += getPartAraCnt( i, j - 1, area );
}
if( j < columnCnt - 1 && area[i][j + 1] != -1 && Math.abs(cellValue - area[i][j + 1]) <= 1)
{
areaCnt += getPartAraCnt( i, j + 1, area );
}
return areaCnt;
}
}
JavaScript代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
while (line = await readline()) {
var rec = line.split(" ");
var rowCnt = parseInt(rec[0]);
var columnCnt = parseInt(rec[1]);
// 第二行数据, 矩形区域
var area = new Array();
for (var i = 0; i < rowCnt; i++) {
line = await readline();
var columns = line.split(" ");
var columnValues = new Array();
for (var j = 0; j < columnCnt; j++) {
columnValues[j] = parseInt(columns[j]);
}
area[i] = columnValues;
}
processRobotMoveArea(area);
}
}();
function processRobotMoveArea(area) {
var maxPartAreaCnt = 0;
for (var i = 0; i < area.length; i++) {
for (var j = 0; j < area[i].length; j++) {
var cellValue = area[i][j];
if (cellValue == -1) {
continue;
}
var partAreaCnt = getPartAraCnt(i, j, area);
if (partAreaCnt > maxPartAreaCnt) {
maxPartAreaCnt = partAreaCnt;
}
}
}
console.log(maxPartAreaCnt);
}
function getPartAraCnt(i, j, area) {
var areaCnt = 0;
var rowCnt = area.length;
var columnCnt = area[0].length;
var cellValue = area[i][j];
area[i][j] = -1;
areaCnt++;
if (i > 0 && area[i - 1][j] != -1 && Math.abs(cellValue - area[i - 1][j]) <= 1) {
areaCnt += getPartAraCnt(i - 1, j, area);
}
if (i < rowCnt - 1 && area[i + 1][j] != -1 && Math.abs(cellValue - area[i + 1][j]) <= 1) {
areaCnt += getPartAraCnt(i + 1, j, area);
}
if (j > 0 && area[i][j - 1] != -1 && Math.abs(cellValue - area[i][j - 1]) <= 1) {
areaCnt += getPartAraCnt(i, j - 1, area);
}
if (j < columnCnt - 1 && area[i][j + 1] != -1 && Math.abs(cellValue - area[i][j + 1]) <= 1) {
areaCnt += getPartAraCnt(i, j + 1, area);
}
return areaCnt;
}
(完)