算法,病毒传播

.病毒扩散
一个输入N个数满足n*n,1表示中病毒,0表示健康。每天有病毒的会感染它的上下左右的格子。求共需多少天所有格子全部感染。当输入全0或者全一的话输出-1,否则输出所需天数。

1.首选,分析

第一眼想到的是dfs,但是再想一想,并不是,因为不需要递归往下深钻,只需要看(x,y)结点的上下左右,因此还是打算用暴力分析,二维数组遍历;

2.如何遍历

简单的,就是碰到1,进行逆时针处理:右(x,y+1)下(x+1,y)左(x,y-1)上(x-1,y),判断节点是否为0,为0就置为1,然后一天下来,遍历一遍整个二维数组,找到1的数量,即感染者数量;

但是,有个问题,就是上下左右,数据由0->1的(例如是:(x+1,y)这个人),不能在今天传染其他人,因为是被传染的,若程序遍历到今天被传染的人因该跳过,今天被传染的这个人即使值已经置为1了,也应该跳过,这该怎么办呢?--想到了可以在新增一个二维数据,对应位置上,保留前一天的感染人员状态(即(x+1,y)这个人在此二维数组上还是为0)

3.实现

代码

static class Virus {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int num = sc.nextInt();
            int[][] maps = new int[num][num];
            int[][] cankao = new int[num][num];
            int base = 0;
            boolean flag = true;
            while (sc.hasNextInt()) {
                for (int x = 0; x < num; x++) {
                    for (int y = 0; y < num; y++) {
                        int n = sc.nextInt();
                        maps[x][y] = n;
                        cankao[x][y] = n;
                        base = maps[0][0];
                        if (base != maps[x][y]) {
                            flag = false;
                        }
                    }
                }
                if (flag) System.out.println(-1);
                chuanBo(maps, cankao);
            }
        }

        static void chuanBo(int[][] map, int[][] cankao) {
            int total = map.length * map[0].length;
            int oneCount = 0;    //被感染人数量
            int d = 1;
            for (; oneCount < total; d++) {
                oneCount = 0;    //每天重新置为0统计
                //iterator map
                for (int x = 0; x < map.length; x++) {
                    for (int y = 0; y < map[0].length; y++) {
                        if (map[x][y] == 1 && cankao[x][y] == 1) {
                            //right
                            if (y + 1 < map[0].length && map[x][y + 1] == 0) {
                                map[x][y + 1] = 1;
                            }
                            //down
                            if (x + 1 < map.length && map[x + 1][y] == 0) {
                                map[x + 1][y] = 1;
                            }
                            //left
                            if (y - 1 >= 0 && map[x][y - 1] == 0) {
                                map[x][y - 1] = 1;
                            }
                            //up
                            if (x - 1 >= 0 && map[x - 1][y] == 0) {
                                map[x - 1][y] = 1;
                            }
                        }
                    }
                }
                //每天扫一遍
                for (int x = 0; x < map.length; x++) {
                    for (int y = 0; y < map[0].length; y++) {
                        if (map[x][y] == 1) {
                            oneCount++;    //每天统计
                            cankao[x][y] = 1;
                        }
                    }
                }
            }
            //output day
            System.out.println(d - 1);
        }
    }

如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值