题目:给定n个破坏轮,告诉坐标和爆炸半径,只要其他破坏轮在当前爆炸半径内就继续引爆,问最多能引爆几个
思路,首先暴力查询一遍每个邻接表能引爆的tnt,用邻接表存储,再对每个炸弹进行深搜,就是一直找寻当前炸弹最多能引爆到第几个(具体在代码),一直到全部都爆炸或者没有在范围内的结束,最后更新最大值;
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
struct vv
{
ll x, y, r; // x,y表示坐标,r表示破坏范围
};
// 检查两个 TNT 破坏轮是否在彼此的破坏范围内
int check(vv a, vv b)
{
ll dx = a.x - b.x;
ll dy = a.y - b.y;
ll dist = dx * dx + dy * dy;
return dist <= a.r * a.r;
}
vector<int> b[N]; // 邻接表存储每个 tnt 破坏轮可以引爆的其他 tnt
int vis[N]; // 记录每个 tnt是否被访问过
// 计算从某个 tnt开始可以引爆的 tnt 数量
void dfs(int from, int &cnt)
{
stack<int> st;
st.push(from);
while (!st.empty())
{
int from = st.top(); // 取出栈顶的 tnt 破坏轮
st.pop();
if (!vis[from]) // 如果该 tnt未被访问过则数量加1
{
vis[from]++;
cnt++;
for (auto to : b[from]) // 寻找从当前tnt可以引爆的其他tnt
{
if (!vis[to]) // 没爆炸过就入栈
{
st.push(to);
}
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
vector<vv> a(n); // 邻接表存储
for (int i = 0; i < n; ++i)
{
cin >> a[i].x >> a[i].y >> a[i].r;
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (i != j && check(a[i], a[j])) // 如果两个 tnt 破坏轮在破坏范围内,将 j 加入 i 的邻接表中
{
b[i].push_back(j);
}
}
}
int ans = 0;
for (int i = 0; i < n; ++i)
{
memset(vis, 0, sizeof(vis));
if (!vis[i]) // 如果该 TNT 破坏轮未被访问过,记录从该tnt 破坏轮开始可以引爆的 tnt 破坏轮数量
{
int cnt = 0;
dfs(i, cnt);
ans = max(ans, cnt); // 更新最多可以引爆的 tnt破坏轮数量
}
}
cout << ans << '\n';
return 0;
}