回溯法:基本做法是搜索,通过x+1、x-1横向遍历,y+1、y-1纵向遍历,获取满足连通的坐标
原始参考链接:【华为OD机试真题 python】查找单入口空闲区域【2022 Q4 | 100分】_无痕de泪的博客-CSDN博客 查找单入口空闲区域 华为OD真题 100_keven000777的博客-CSDN博客
java题解(输入时一次性输入):
import java.util.*;
import java.util.Scanner;
public class test20230131 {
static int count=0;//入口统计,方便筛选单入口信息
//入口的坐标信息,如果存在入口,只能是单入口,所以一个长度为2的数组即可
static int[] entryInfo=new int[2];
//输入信息:二维数组和数组的x、y
static String[][] data;
static int m=0;
static int n=0;
public static void main(String[] args){
Scanner in=new Scanner(System.in);
String numStr=in.nextLine();
m=Integer.parseInt(numStr.split(" ")[0]);
n=Integer.parseInt(numStr.split(" ")[1]);
data=new String[m][n];
for(int i=0;i<m;i++){
String str=in.nextLine();
String str1[]=str.split(" ");
for(int j=0;j<n;j++){
data[i][j]=str1[j];
}
}
int max=0;
List<int[]> areaDress = new ArrayList<>(); //最大区域的入口坐标和其区域大小的集合
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(data[i][j].equals("O")){
//记录每次遍历的入口坐标
List<int[]> allList=new ArrayList<>();
//遍历完,后面不再遍历,即将O置为X
data[i][j]="X";
allList.add(new int[]{i,j});
findArea(i,j,allList);
if(count==1){//通过count==1来筛选单入口区域
if(max==allList.size()){//有多种单入口区域大小相同情况,只用输出大小max
areaDress.clear();
}else if(max<allList.size()){
//获取单入口的最大区域
max=allList.size();
areaDress.clear();
areaDress.add(new int[]{entryInfo[0],entryInfo[1],max});
}
}
//下一个坐标遍历时,重置数据;
count=0;
entryInfo=new int[2];
}
}
}
//单入口里面坐标及大小
if(areaDress.size()==1){
System.out.println(areaDress.get(0)[0]+" "+areaDress.get(0)[1]+" "+areaDress.get(0)[2]);
}else if(max!=0){//quyu为空时,存在max!=0,即存在重复大小的单入口区域
System.out.println(max);
}else {//不存在单入口区域
System.out.println("NULL");
}
}
//递归遍历x+1或y+1区域,寻找连通区域
public static void findArea(int x,int y,List<int[]> allList){
//边界入口:
if(x==0 || x==m-1 || y==0 || y==n-1){
count++;//入口统计
//获取入口坐标信息
entryInfo[0]=x;
entryInfo[1]=y;
}
if(x<m-1){
if(data[x+1][y].equals("O")){
data[x+1][y]="X";
allList.add(new int[]{x+1,y});
findArea(x+1,y,allList);
}
}
if(y<n-1){
if(data[x][y+1].equals("O")){
data[x][y+1]="X";
allList.add(new int[]{x,y+1});
findArea(x,y+1,allList);
}
}
if(x-1>=0){
if(data[x-1][y].equals("O")){
data[x-1][y]="X";
allList.add(new int[]{x-1,y});
findArea(x-1,y,allList);
}
}
if(y-1>=0){
if(data[x][y-1].equals("O")){
data[x][y-1]="X";
allList.add(new int[]{x,y-1});
findArea(x,y-1,allList);
}
}
}
}
//另外:data[x][y+1].equals("O")不能写成data[x][y+1]=="O";做题细节要注意
python题解:
#相关全局变量
str=input()
m=int(str.split(" ")[0])
n=int(str.split(" ")[1])
#data接收输入的X、O数据
data=[]
for i in range(m):
str1=input()
data1=[]
for j in range(n):
data1.append(str1.split(" ")[j])
data.append(data1)
Max=0
count=0
#存储入口坐标
entryInfo=[0,0]
#存储坐标加连通区域大小
allData=[]
def gainDataAdress(x, y,areaDress):
if(x==0 or x==m-1 or y==0 or y==n-1):
global count
count+=1
#获取坐标
entryInfo[0]=x
entryInfo[1]=y
if(x<m-1):
if(data[x+1][y]=="O"):
data[x+1][y]="X"
listreData=[x+1,y]
areaDress.append(listreData)
gainDataAdress(x+1,y,areaDress)
if (y < n - 1):
if (data[x][y+1] == "O"):
data[x][y+1] = "X"
listreData=[x,y+1]
areaDress.append(listreData)
gainDataAdress(x, y+1, areaDress)
if(x-1>=0):
if(data[x-1][y]=="O"):
data[x-1][y]="X"
listreData=[x-1,y]
areaDress.append(listreData)
gainDataAdress(x-1,y,areaDress)
if(y-1>=0):
if(data[x][y-1]=="O"):
data[x][y-1]="X"
listreData=[x,y-1]
areaDress.append(listreData)
gainDataAdress(x,y-1,areaDress)
for p in range(m):
for q in range(n):
if(data[p][q]=="O"):
areaDress = []
areaDress.append([p,q])
data[p][q]="X"
gainDataAdress(p,q,areaDress)
#单入口区域
if(count==1):
#存在多个单入口区域
if(Max==len(areaDress)):
allData.clear()
elif(Max<len(areaDress)):
Max=len(areaDress)
allData.clear()
allData.append(entryInfo+[Max])
count=0
entryInfo=[0,0]
if(len(allData)==1):
print(allData[0][0],allData[0][1],allData[0][2])
elif(Max!=0):
print(Max)
else:
print("NULL")
欢迎指正,未完待续~