- 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;
}