题目大意:
有点像扫雷游戏,炸弹爆炸的时候就像BFS一样。要确定爆炸的范围。
题目分析:
数据很大,暴力会超时。那么只有离散化以后,在枚举了。
注意枚举的上界和下届,很显然,对于x坐标的下界为x2-x1,上界为x2+x1;对于y坐标的下界为y2-y1,,上界为y2+y1。
下面是代码:
#include <stdio.h>
#include <string.h>
#include <queue>
#include <set>
#include <math.h>
#include <algorithm>
using namespace std;
const int maxn = 101000;
int n,m,cnt;
int X[maxn];
int vis[maxn];
struct node
{
int y;
int id;
node(int a,int b)
{
id = a;
y = b;
}
bool operator < (const node &c) const
{
return y < c.y;
}
};
struct Mine
{
int x;
int y;
int d;
} M[maxn];
multiset<node> G[maxn];
int bfs(int x)
{
int ans = 0;
if(vis[x]) return ans;
vis[x] = 1;
queue<int> q;
q.push(x);
multiset<node>::iterator yl,yr,it;
while(!q.empty())
{
ans++;
int k = q.front(); q.pop();
int l = lower_bound(X,X+cnt,M[k].x-M[k].d) - X;
int r = upper_bound(X,X+cnt,M[k].x+M[k].d) - X;
//printf("k = %d l = %d r = %d\n",k,l,r);
for(int i = l; i < r; i++)
{
int dy = M[k].d - abs(M[k].x - X[i]);
yl = G[i].lower_bound(node(0,M[k].y-dy));
yr = G[i].upper_bound(node(0,M[k].y+dy));
for(it = yl; it != yr; it++)
{
if(!vis[it->id])
{
//printf("it->id = %d\n",it->id);
vis[it->id] = 1;
q.push(it->id);
}
}
G[i].erase(yl,yr);
}
}
return ans;
}
int main()
{
int T = 0;
while(scanf("%d",&n) && n)
{
cnt = 0;
for(int i = 0; i < n; i++)
{
scanf("%d%d%d",&M[i].x,&M[i].y,&M[i].d);
X[cnt++] = M[i].x;
}
sort(X,X+cnt);
cnt = unique(X,X+cnt) - X;
for(int i = 0; i < cnt; i++) G[i].clear();
for(int i = 0; i < n; i++)
{
int id = lower_bound(X,X+cnt,M[i].x) - X;
G[id].insert(node(i,M[i].y));
}
scanf("%d",&m);
printf("Case #%d:\n",++T);
memset(vis,0,sizeof(vis));
for(int i = 0; i < m; i++)
{
int id;
scanf("%d",&id);
printf("%d\n",bfs(id-1));
}
}
return 0;
}