HDU 4400 Mines(好题!分两次计算距离)

http://acm.hdu.edu.cn/showproblem.php?pid=4400

题意:

在笛卡尔坐标中有多个炸弹,每个炸弹有一个坐标值和一个爆炸范围。现在有多次操作,每次引爆一个炸弹,问每次操作会有多少个炸弹爆炸。

 

思路:

需要注意的是一个炸弹爆炸后会引起别的炸弹爆炸,然后别的炸弹爆炸后又会引起别的炸弹爆炸。

可以考虑bfs,但是必须需要优化,首先对x坐标进行离散化,然后将该坐标的y值和id值(第几个炸弹)存入multiset中,不同的x存入不同的multiset中。当我们进行寻找时,首先可以确定x的范围,当确定了x的范围之后,对于该x值我们又可以确定y的范围,这样只需要在multiset中进行二分查找即可。不得不说这个做法实在是太妙了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<set>
 5 #include<queue>
 6 #include<cstring>
 7 using namespace std;
 8 const int maxn = 100000+5;
 9 
10 int n, num;
11 int x[maxn],y[maxn],d[maxn],b[maxn];
12 bool del[maxn];
13 
14 struct node
15 {
16     int y,id;
17     node(int y, int id):y(y),id(id){}
18     bool operator< (const node& rhs) const
19     {
20         return y<rhs.y;
21     }
22 };
23 
24 multiset<node> s[maxn];
25 multiset<node>::iterator ly, ry, it;
26 
27 void solve()
28 {
29     priority_queue<int> q;
30     memset(del,false,sizeof(del));
31     int m; scanf("%d",&m);
32     while(m--)
33     {
34         int t; scanf("%d",&t); t--;
35         if(del[t])  {puts("0");continue;}
36         while(!q.empty())  q.pop();
37         q.push(t);
38         del[t] = true;
39         int ans = 0;
40         while(!q.empty())
41         {
42             ans++;
43             t = q.top(); q.pop();
44             int lx = lower_bound(b,b+num,x[t]-d[t])-b;
45             int rx = upper_bound(b,b+num,x[t]+d[t])-b;
46             for(int i=lx;i<rx;i++)
47             {
48                 int dis = d[t]-abs(x[t]-b[i]);
49                 ly = s[i].lower_bound(node(y[t]-dis,0));
50                 ry = s[i].upper_bound(node(y[t]+dis,0));
51                 for(it=ly;it!=ry;it++)
52                 {
53                     if(!del[it->id])
54                     {
55                         del[it->id] = true;
56                         q.push(it->id);
57                     }
58                 }
59                 s[i].erase(ly,ry);
60             }
61         }
62         printf("%d\n",ans);
63     }
64 }
65 
66 int main()
67 {
68     //freopen("in.txt","r",stdin);
69     int kase = 0;
70     while(~scanf("%d",&n) && n!=0)
71     {
72         printf("Case #%d:\n",++kase);
73         for(int i=0;i<n;i++)
74         {
75             scanf("%d%d%d",&x[i],&y[i],&d[i]);
76             b[i] = x[i];
77         }
78         sort(b,b+n);
79         num = unique(b,b+n)-b;
80         for(int i=0;i<n;i++)  s[i].clear();
81         for(int i=0;i<n;i++)
82         {
83             int tmp = lower_bound(b,b+num,x[i])-b;
84             s[tmp].insert(node(y[i],i));
85         }
86         solve();
87     }
88     return 0;
89 }

 

posted @ 2017-12-03 16:23  Kayden_Cheung  阅读(270)  评论(0编辑  收藏  举报
//目录