LeetCode第2101题引爆最多的炸弹(c++)

给你一个炸弹列表。一个炸弹的 爆炸范围 定义为以炸弹为圆心的一个圆。

炸弹用一个下标从 0 开始的二维整数数组 bombs 表示,其中 bombs[i] = [xi, yi, ri] 。xi 和 yi 表示第 i 个炸弹的 X 和 Y 坐标,ri 表示爆炸范围的 半径 。

你需要选择引爆 一个 炸弹。当这个炸弹被引爆时,所有 在它爆炸范围内的炸弹都会被引爆,这些炸弹会进一步将它们爆炸范围内的其他炸弹引爆。

给你数组 bombs ,请你返回在引爆 一个 炸弹的前提下,最多 能引爆的炸弹数目。

示例 1:

输入:bombs = [[2,1,3],[6,1,4]]
输出:2
解释:
上图展示了 2 个炸弹的位置和爆炸范围。
如果我们引爆左边的炸弹,右边的炸弹不会被影响。
但如果我们引爆右边的炸弹,两个炸弹都会爆炸。
所以最多能引爆的炸弹数目是 max(1, 2) = 2 。
示例 2:

输入:bombs = [[1,1,5],[10,10,5]]
输出:1
解释:
引爆任意一个炸弹都不会引爆另一个炸弹。所以最多能引爆的炸弹数目为 1 。
示例 3:

输入:bombs = [[1,2,3],[2,3,1],[3,4,2],[4,5,3],[5,6,4]]
输出:5
解释:
最佳引爆炸弹为炸弹 0 ,因为:
- 炸弹 0 引爆炸弹 1 和 2 。红色圆表示炸弹 0 的爆炸范围。
- 炸弹 2 引爆炸弹 3 。蓝色圆表示炸弹 2 的爆炸范围。
- 炸弹 3 引爆炸弹 4 。绿色圆表示炸弹 3 的爆炸范围。
所以总共有 5 个炸弹被引爆。
 

提示:

1 <= bombs.length <= 100
bombs[i].length == 3
1 <= xi, yi, ri <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/detonate-the-maximum-bombs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

实现思路:

依次将炸弹放入队列中,如果炸弹爆炸范围内有其他炸弹,就一起入队,并逐个结算。

实现代码:

class Solution {
public:
    int maximumDetonation(vector<vector<int>>& bombs) {
        int max=0,n=bombs.size();
        int cnt=0;
        queue<vector<int>> q;   
        for(int i=0;i<n;i++){
            bool visited[101]={false};
            if(!visited[i]){
                q.push(bombs[i]);
                visited[i]=true;
                cnt=1;
                while(!q.empty()){
                    auto tmp=q.front();
                    q.pop();
                    for(int j=0;j<n;j++){
                        if((tmp[2]/100.0)*(tmp[2]/100.0)>=
                        (bombs[j][0]-tmp[0])/100.0*((bombs[j][0]-tmp[0])/100.0)+
                        ((bombs[j][1]-tmp[1])/100.0)*((bombs[j][1]-tmp[1])/100.0)
                        &&!visited[j]){
                            visited[j]=true;
                            q.push(bombs[j]);
                            cnt++;
                        }
                    }
                }
            }
            max=max>cnt?max:cnt;
        }
        return max;
    }
};

这里要注意一点,它给的数字太大了,可能会溢出,所以最好在判断是否在爆炸范围的过程中每步运算除以100.0。 

不过这样太慢了,考虑一下优化,让中途炸过的炸弹在最开始的遍历中就不再考虑了,也就是剪纸。

class Solution {
public:
    int maximumDetonation(vector<vector<int>>& bombs) {
        int max=0,n=bombs.size();
        int cnt=0;
        queue<vector<int>> q;
        bool visited[101]={false};
        for(int i=0;i<n;i++){
            bool bombed[101]={false}; 
            if(!visited[i]){
                q.push(bombs[i]);
                visited[i]=true;
                bombed[i]=true;
                cnt=1;
                while(!q.empty()){
                    auto tmp=q.front();     
                    for(int j=0;j<n;j++){
                        if((tmp[2]/100.0)*(tmp[2]/100.0)
                        >=(bombs[j][0]-tmp[0])/100.0*((bombs[j][0]-tmp[0])/100.0)
                        +((bombs[j][1]-tmp[1])/100.0)*((bombs[j][1]-tmp[1])/100.0)
                        &&!bombed[j]){
                            visited[j]=true;
                            bombed[j]=true;
                            q.push(bombs[j]);
                            cnt++;
                        }
                    }
                    q.pop();
                }
            }
            max=max>cnt?max:cnt;
        }
        return max;
    }
};

加了一个bombed数组,用来判断它是否炸过。速度快了三倍。不过还是好慢。。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值