bzoj1822: [JSOI2010]Frozen Nova 冷冻波

1822: [JSOI2010]Frozen Nova 冷冻波

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1640  Solved: 516
[Submit][Status][Discuss]

Description

WJJ喜欢“魔兽争霸”这个游戏。在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵。我们认为,巫妖和小精灵都可以看成是平面上的点。 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵。 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放。不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以杀死一个小精灵。 现在巫妖的头目想知道,若从0时刻开始计算,至少需要花费多少时间,可以杀死所有的小精灵?

Input

输入文件第一行包含三个整数N、M、K(N,M,K<=200),分别代表巫妖的数量、小精灵的数量和树木的数量。 接下来N行,每行包含四个整数x, y, r, t,分别代表了每个巫妖的坐标、攻击范围和施法间隔(单位为秒)。 再接下来M行,每行两个整数x, y,分别代表了每个小精灵的坐标。 再接下来K行,每行三个整数x, y, r,分别代表了每个树木的坐标。 输入数据中所有坐标范围绝对值不超过10000,半径和施法间隔不超过20000。

Output

输出一行,为消灭所有小精灵的最短时间(以秒计算)。如果永远无法消灭所有的小精灵,则输出-1。

Sample Input

2 3 1
-100 0 100 3
100 0 100 5
-100 -10
100 10
110 11
5 5 10

Sample Output

5

HINT

 

二分完用流判定...计算几何....

 1 #include<bits/stdc++.h>
 2 #define rep(i,l,r) for(int i=l;i<=r;++i)
 3 using namespace std;
 4 typedef double d;
 5 const int N=102333,inf=1e8;
 6 int head[N],tot=1,Dis[N],n,m,K,l,r,mid,ans,T;
 7 struct Edge{
 8     int to,next,w;
 9 }e[N];
10 struct node{
11     int x,y,t,r;
12 }a[N],b[N],c[N];
13 inline node operator-(node a,node b){
14     node t;t.x=a.x-b.x;t.y=a.y-b.y;return t;
15 }
16 inline d operator*(node a,node b){
17     return a.x*b.y-a.y*b.x;
18 }
19 inline d dot(node a,node b){
20     return a.x*b.x+a.y*b.y;
21 }
22 inline d dis(node a,node b){
23     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
24 }
25 inline d dis(node a,node b,node p){
26     if(dot(a-p,b-p)>0)
27         return min(dis(a,p),dis(b,p));
28     return abs((p-a)*(b-a)/dis(a,b));
29 }
30 bool pd(int x,int y){
31     if(dis(a[x],b[y])>a[x].r)return 0;
32     rep(i,1,K)if(dis(a[x],b[y],c[i])<c[i].r)return 0;
33     return 1;
34 }
35 inline bool bfs(){
36      for(int i=0;i<=T;i++) Dis[i]=-1; queue<int>q; q.push(0); Dis[0]=0;
37      while(!q.empty()) {
38           int x=q.front(); q.pop();
39           for(int k=head[x];k;k=e[k].next) 
40              if(Dis[e[k].to]<0 && e[k].w>0) {
41                    Dis[e[k].to]=Dis[x]+1; q.push(e[k].to);
42              }
43      }
44      if(Dis[T]>0) return 1;else return 0;
45 }
46 int find(int x,int low){
47      if(x==T) return low;
48      int delta=low,now;
49      for(int k=head[x];k;k=e[k].next) 
50        if(e[k].w>0 && Dis[e[k].to]==Dis[x]+1){ 
51            now=find(e[k].to,min(e[k].w,delta));
52            e[k].w-=now; e[k^1].w+=now;   delta-=now;
53            if(!delta) return low;
54         } 
55      Dis[x]=-1;
56      return low-delta;
57 }
58 inline void ins(int u,int v,int w) {
59      e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w;
60 }
61 inline void insert(int u,int v,int w) {
62     ins(u,v,w); ins(v,u,0);
63 }
64 inline bool run(int x){
65     memset(head,0,sizeof head); tot=1;
66     rep(i,1,n) insert(0,i,x/a[i].t+1);
67     rep(i,1,n) rep(j,1,m) if(pd(i,j))insert(i,j+n,1);
68     rep(i,1,m) insert(i+n,T,1);
69     int sum=0;
70     while(bfs())sum+=find(0,inf);
71     return sum==m;
72 }
73 int main(){
74     scanf("%d%d%d",&n,&m,&K);
75     rep(i,1,n) scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].r,&a[i].t);
76     rep(i,1,m) scanf("%d%d",&b[i].x,&b[i].y);
77     rep(i,1,K) scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].r);
78     ans=-1; r=20000*200; T=1+n+m;
79     while(l<=r){
80         int mid=l+r>>1;
81         if(run(mid)) ans=mid,r=mid-1;else l=mid+1;
82     }
83     printf("%d\n",ans);
84 }
View Code

 

posted @ 2016-12-26 19:36  Bloodline  阅读(251)  评论(0编辑  收藏  举报