DFS应用:纵火犯题解

【问题描述】

给你一块n*m的草坪,问如果只点一次火,最多能烧多少块草坪。可以从n*m的草地中任意一个地方开始点火,火只能往上下左右传递,没有草的地方不能燃烧。

【输入格式

输入由多个测试例组成。每个测试例的第一行含两个整数n和m, (1 <=n,m<=100), 分别表示01矩阵的行数与列数,

后面紧跟着n行,每行含m个整数0或1,1代表草坪,0表示啥也没有,相邻两个整数之间用一个空格隔开,两个测

试例之间用一个空行隔开,最后一个测试例之后隔一个空行,最后一行含有两个整数0,表示输入结束。

【输出格式

每个测试例对应一行输出,含一个整数,表示只点一次火最多能烧的草坪个数。

样例输入

5 6

0 1 1 0 0 1

1 1 0 1 0 1

0 1 0 0 1 0

0 0 0 1 1 1

1 0 1 1 1 0

0 0

样例输出

7

该题可以跟连通块结合

核心代码:

首先草坪想要烧起来,只能上下左右烧,并且得判断是否是1,是1才能烧起来。所以设置四个方向的遍历,采用了数组的方式。

int f[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};

 草坪每烧一个采用计数变量计数,并且下一个草坪也会进行一个上下左右的方向,因此便是四个方向的深度遍历,并且需要对草坪进行判断,防止越界,以及判断草坪为1。

for(int i=0; i<4; i++) {
		int dx = x+f[i][0];
		int dy = y+f[i][1];
		if(dx>=0 && dy>=0 && dx<m && dy<n && a[dx][dy]==1) {
			a[dx][dy]=0;
			dfs(dx,dy);
		}
	}

 优化代码:

public class Test3 {
    static int a[][]=new int[100][100];
    //方向数组上下左右
    static int f[][]= {{0,1},{0,-1},{1,0},{-1,0}};
    //标志数用于记录个数
    static int max=0;
    static int n;
    static int m;
    static int cout=1;

    static void dfs(int x,int y){

        a[x][y]=0;

        //对四个方向的深度遍历
        for(int i=0; i<4; i++) {
            int dx = x+f[i][0];
            int dy = y+f[i][1];
            //防止越界,以及对1的草坪进行点火
            if(dx>=0 && dy>=0 && dx<m && dy<n && a[dx][dy]==1) {
                a[dx][dy]=0;
                dfs(dx,dy);
                cout++;
            }
        }

    }

    public static void main(String [] args){
        Scanner scan = new Scanner(System.in);

        m= scan.nextInt();
        n= scan.nextInt();
        //对数组赋值0,1
        for (int i=0;i<m;i++) {
            for (int j = 0; j < n; j++) {
                a[i][j] = scan.nextInt();
            }
        }
        //遍历找到1的草坪点火,0的略过
        for (int i=0;i<m;i++) {
            for (int j = 0; j < n; j++) {
                if(a[i][j]==1) {
                    dfs(i, j);
                    max=max>cout?max:cout;
                    cout=1;
                }
            }
        }

        System.out.println(max);

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值