华为OD真题学习-查找单入口空闲区域 100

回溯法:基本做法是搜索,通过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")

欢迎指正,未完待续~

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值