tnt破坏轮

题目:给定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 d = dx * dx + dy * dy;
	return d <= 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 (int i = 0; i < b[from].size(); i++) // 寻找从当前tnt可以引爆的其他tnt
			{
				if (!vis[b[from][i]]) // 没爆炸过就入栈
				{
					st.push(b[from][i]);
				}
			}
		}
	}
}
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));//因为对于每一次for,都是从当前位置重新开始一遍dfs,所以vis数组要清零
		if (!vis[i]) // 如果该 TNT 破坏轮未被访问过,记录从该tnt 破坏轮开始可以引爆的 tnt 破坏轮数量
		{
			int cnt = 0;
			dfs(i, cnt);
			ans = max(ans, cnt); // 更新最多可以引爆的 tnt破坏轮数量
		}
	}
	cout << ans << '\n';
	return 0;
}


posted @ 2024-07-25 15:47  台州第一深情  阅读(16)  评论(0编辑  收藏  举报