福大大

  1. 2022-05-17:在一个地图上有若干个炸弹,每个炸弹会呈现十字型引爆。
    每个炸弹都有其当量值,这个值决定了这个炸弹的爆炸半径。
    如果一个炸弹被引爆时,有其它炸弹在其爆炸半径内,那么其它炸弹也会爆炸。
    请问使地图上所有炸弹爆炸所需的最少人为引爆次数。
    例如:
    0,0,0,0,0
    0,0,0,1,0
    0,0,0,0,0
    上图中val为1的单元是一个炸弹,人为引爆后地图变成下面的样子:
    0, 0, 0,-1, 0
    0, 0,-1,-1,-1
    0, 0, 0,-1, 0
    题目并没有给数据量,面经题目的通病。
    来自亚马逊。
    ————————————————
    版权声明:本文为CSDN博主「福大大架构师每日一题」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_48502062/article/details/124828246
/**
*强连通分量:指的是一个集合内部的所有点都是可以互通的。每俩个点都互相连通,则是强连通。scc
*Korasaju算法:
*
*/
 public int minBombs(int[][] map){
        //预测 炸弹列表
        //预测 存在计数器
        //预测 循环
        //预测 炸弹之间的关联关系
        //预测 队列数据结构
        //预测

        //地图的长度
        int n = map.length;
        //记录参数
        int m=0;
        //循环遍历地图的长度
        for (int i=0;i<n;i++){
            //循环遍历地图的宽度
            for (int j=0;j<n;j++){
                //叠加和 炸弹个数
                m+=map[i][j] ==0?0:1;
            }
        }
        //新建炸弹数组
        int[][] bombs = new int[m][2];
        //重新赋值
        m =0;
        //循环地图的长度
        for (int i=0;i<n;i++){
            //循环地图的宽度
            for (int j=0;j<n;j++){
                //预测 这是给炸弹
                if (map[i][j] !=0){
                    //横坐标
                    bombs[m][0] = i;
                    //纵坐标
                    bombs[m++][1] =j;
                }
            }
        }
        //新建炸弹数组
        int[] arr = new int[m];
        //遍历数组给数组重新赋值
        for (int i=0;i<m;i++){
            arr[i] =i;
        }
        //开始递归
        return process1(arr,0,bombs,map);
    }
    private int process1(int[] arr, int index, int[][] bombs, int[][] map) {
        //定义一个最大值
        int ans = Integer.MAX_VALUE;
        //预测其中的一个分支 炸弹炸完
        if (index == arr.length){
            //返回其中一个分支 次数
            ans = orderIgnite(arr,bombs,map);
        }else {
            //循环剩余的炸弹
            for (int i= index;i<arr.length;i++){
                //转换条件
                swap(arr,index,i);
                //递归处理
                ans = Math.min(ans,process1(arr,index+1,bombs,map));
                //条件回滚
                swap(arr,index,i);
            }
        }
        return ans;
    }
    private int orderIgnite(int[] arr, int[][] bombs, int[][] map) {
        //新建一个拷贝数组(不改变原数组的值)
        int[][] copy = copyMap(map);
        //定义变量
        int ans =0;
        //循环炸弹数组
        for (int i:arr){
            //获取横坐标
            int row = bombs[i][0];
            //获取纵坐标
            int col = bombs[i][1];
            //预测这个炸弹是自己引爆的
            if (copy[row][col] != -1){
                //自己引爆的加一
                ans++;
                //这个引爆的炸弹范围
                burn(copy,row,col,copy[row][col]);
            }
        }
        return ans;
    }
    private void burn(int[][] map, int i, int j, int v) {
        //设置这个爆炸点为-1
        map[i][j] = -1;
        //新建一个队列
        ArrayList<int[]> queue = new ArrayList<>();
        //往左边炸
        for (int row = i-1,cnt =1;row>=0&&cnt<v;row--,cnt++){
            //预测左边这个点是炸弹
            if (map[row][j]>0){
                //把这个炸弹加入队列中
                queue.add(new int[]{row,j,map[row][j]});
            }
            //这个点进行爆炸
            map[row][j] = -1;
        }
        //往右边炸
        for (int row = i + 1, cnt = 1; row < map.length && cnt <= v; row++, cnt++) {
            if (map[row][j] > 0) {
                queue.add(new int[] { row, j, map[row][j] });
            }
            map[row][j] = -1;
        }
        for (int col = j - 1, cnt = 1; col >= 0 && cnt <= v; col--, cnt++) {
            if (map[i][col] > 0) {
                queue.add(new int[] { i, col, map[i][col] });
            }
            map[i][col] = -1;
        }
        for (int col = j + 1, cnt = 1; col < map.length && cnt <= v; col++, cnt++) {
            if (map[i][col] > 0) {
                queue.add(new int[] { i, col, map[i][col] });
            }
            map[i][col] = -1;
        }
        //进行引爆其他的炸弹
        for (int[] next : queue) {
            burn(map, next[0], next[1], next[2]);
        }

    }

    public  int[][] copyMap(int[][] map) {
        int n = map.length;
        int[][] ans = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                ans[i][j] = map[i][j];
            }
        }
        return ans;
    }

posted @ 2022-05-18 11:44  一棵小萌新  阅读(44)  评论(0)    收藏  举报