题目描述
现有一个机器人,可放置于 M × N 的网格中任意位置,每个网格包含一个非负整数编号,当相邻网格的数字编号差值的绝对值小于等于 1 时,机器人可以在网格间移动。
问题: 求机器人可活动的最大范围对应的网格点数目。
**说明:**网格左上角坐标为 (0,0) ,右下角坐标为(m−1,n−1),机器人只能在相邻网格间上下左右移动
输入描述
第 1 行输入为 M 和 N , M 表示网格的行数 N 表示网格的列数
之后 M 行表示网格数值,每行 N 个数值(数值大小用 k 表示),
数值间用单个空格分隔,行首行尾无多余空格。
M、 N、 k 均为整数,且 1 ≤ M,N ≤ 150, 0 ≤ k ≤ 50
输出描述
输出 1 行,包含 1 个数字,表示最大活动区域的网格点数目,
行首行尾无多余空格。
用例
输入 4 4
1 2 5 2
2 4 4 5
3 5 7 1
4 6 2 4
输出 6
说明
相邻网格差值绝对值都小于等于 1 ,且为最大区域,对应网格点数目为 6。
输入
2 3
1 3 5
4 1 3
输出
1
解题思路
根据题目,我们可以得知:
- 棋盘大小为[m−1,n−1]
- 机器人的起始点为[0,0][0,0]
- 到达一个格子后,只能往相邻的格子上下左右移动
- 不能斜对角和跳跃,坐标的数字之和不能大于1
代码
java
import java.util.Scanner;
public class MovingCount {
public static void main(String[] args) {
System.out.println("请输入方格的行数m:");
int m = scanner.nextInt();
System.out.println("请输入方格的列数n:");
int n = scanner.nextInt();
MovingCount count = new MovingCount();
int movingCount = count.movingCount(1, m, n);
System.out.println("机器人走了:" + movingCount + "步");
}
/**
* 回溯算法
*
* @param threshold
* 约束值
* @param rows
* 方格行数
* @param cols
* 方格列数
* @return 最多可走的方格数
*/
private int movingCount(int threshold, int rows, int cols) {
if (threshold < 0 || rows <= 0 || cols <= 0) {
return 0;
}
// 访问标识数组
boolean[] visited = new boolean[rows * cols];
// 全部置为false
for (int i = 0; i < rows * cols; i++) {
visited[i] = false;
}
int count = movingCountCore(threshold, rows, cols, 0, 0, visited);
return count;
}
/**
* 计算步数
*
* @param threshold
* @param rows
* @param cols
* @param row
* @param col
* @param visited
* @return
*/
private int movingCountCore(int threshold, int rows, int cols, int row,
int col, boolean[] visited) {
int count = 0;
if (check(threshold, rows, cols, row, col, visited)) {
visited[row * cols + col] = true;
count = 1
+ movingCountCore(threshold, rows, cols, row - 1, col,
visited)
+ movingCountCore(threshold, rows, cols, row, col - 1,
visited)
+ movingCountCore(threshold, rows, cols, row + 1, col,
visited)
+ movingCountCore(threshold, rows, cols, row, col + 1,
visited);
}
return count;
}
/**
* 判断机器人能否进入坐标为(row,col)的方格
*
* @param threshold
* @param rows
* @param cols
* @param row
* @param col
* @param visited
* @return
*/
private boolean check(int threshold, int rows, int cols, int row, int col,
boolean[] visited) {
if (row >= 0 && row < rows && col >= 0 && col < cols
&& getDigitSum(row) + getDigitSum(col) <= threshold
&& !visited[row * cols + col]) {
return true;
}
return false;
}
/**
* 得到一个数字的数位之和
*
* @param number
* 一个数字
* @return 数字的位数之和
*/
private int getDigitSum(int number) {
int sum = 0;
while (number > 0) {
sum += number % 10;
number /= 10;
}
return sum;
}
}
C++
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int M,N;
int f[22501];
int find(int x) {
return x==f[x]?x:(f[x]=find(f[x]));
}
void merge(int i,int j) {
int a=find(i);
int b=find(j);
if(a!=b){
f[a]=b;
}
}
int main() {
cin>>M>>N;
int arr[M][N];
for(int i=0;i<M;i++) {
for(int j=0;j<N;j++) {
cin>>arr[i][j];
}
}
for(int i=1;i<=M*N;i++) {
f[i]=i;
}
for(int i=0;i<M;i++) {
for(int j=0;j<N;j++) {
int ind=i*N+j+1;
if(j+1<N && abs(arr[i][j]-arr[i][j+1])<=1) {
//cout<<ind<<" "<<ind+1<<endl;
merge(ind,ind+1);
}
if(i+1<M && abs(arr[i][j]-arr[i+1][j])<=1) {
merge(ind,ind+N);
}
}
}
map<int,int> mp;
for(int i=1;i<=M*N;i++) { //M*N写成M+N了,还死活查不出来
int a=find(i);
cout<<a<<endl;
mp[a]++;
}
int res=0;
for(auto m:mp) {
if(m.second>res) {
res=m.second;
}
}
cout<<res<<endl;
system("pause");
return 0;
}
Python
class UF:
def __init__(self,n):
self.n=n
self.Fa=[]
def init(self):
for i in range(self.n):
self.Fa.append(i)
def find(self,x):
if x==self.Fa[x]:
return x
else:
self.Fa[x]=self.find(self.Fa[x])
return self.Fa[x]
def merge(self,x,y):
a=self.find(x)
b=self.find(y)
if a!=b:
self.Fa[a]=b
arr=[]
m,n=input().split()
m=int(m)
n=int(n)
for i in range(m):
vec=input().split()
tmp=[]
for j in vec:
tmp.append(int(j))
arr.append(tmp)
uf=UF(m*n)
uf.init()
for i in range(m):
for j in range(n):
if i+1<m and abs(arr[i][j]-arr[i+1][j])<=1:
uf.merge(i*n+j,i*n+j+n)
if j+1<n and abs(arr[i][j]-arr[i][j+1])<=1:
uf.merge(i*n+j,i*n+j+1)
map={}
res=0
for i in range(m*n):
t=uf.find(i)
if t not in map:
map[t]=0
map[t]+=1
res=max(res,map[t])
print(res)
js
/**
* @param {number} m
* @param {number} n
* @param {number} k
* @return {number}
*/
//用于计算数字之和
function sum(i, j) {
let sum = 0
for (let x of i+'') {
sum += Number(x)
}
for (let y of j+'') {
sum += Number(y)
}
return sum
}
var movingCount = function (m, n, k) {
//创建状态矩阵
let status = new Array(m).fill(0)
for(let x=0;x<m;x++){
status[x]= new Array(n).fill(0)
}
status[0][0] = 1
let res = 0
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (i > m || j > n || sum(i, j) > k) {
continue
}
//与相邻格子进行或运算
if (i >= 1) {
status[i][j] |= status[i - 1][j]
}
if (j >= 1) {
status[i][j] |= status[i][j - 1]
}
//统计
if(status[i][j]==1) {res++}
}
}
return res;
};