Bzoj1822 [JSOI2010]Frozen Nova 冷冻波
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1933 Solved: 608
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
-100 0 100 3
100 0 100 5
-100 -10
100 10
110 11
5 5 10
Sample Output
5
HINT
Source
图论 网络流 计算几何
没什么意义的板子题
$O(n^3)$用计算几何判断每个巫妖能攻击到哪些小精灵。只需要判断巫妖到小精灵的连线是否与代表树的圆相离即可。
二分答案,用最大流check限定时间内能否将小精灵消灭完:
源点向每个小精灵连边,容量为1;
每个小精灵向能攻击到它的巫妖连边,容量为1
每个巫妖向汇点连边,容量为限定时间内的最多攻击次数。
(注意技能没有开场CD,时间为0时即可攻击)
(看上去像是简单的网络流+简单的计算几何凑了一道码农题)
——Frozen Nova霜冻新星 怎么翻译成冷冻波这种奇怪的名字啊? (亡灵族玩家激怒)
——为什么要屠杀小精灵啊? (NE玩家激怒)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<vector> 8 #define LL long long 9 using namespace std; 10 const int INF=0x3f3f3f3f; 11 const int mxN=100010; 12 const int mxn=205; 13 int read(){ 14 int x=0,f=1;char ch=getchar(); 15 while(ch<'0' || ch>'9'){if(ch=='-')f=-f;ch=getchar();} 16 while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();} 17 return x*f; 18 } 19 struct edge{ 20 int u,v,nxt,f; 21 }e[mxN]; 22 int hd[mxn*mxn],mct=1; 23 int n,m,S,T,d[mxN]; 24 void add_edge(int u,int v,int f){ 25 e[++mct].v=v;e[mct].u=u;e[mct].nxt=hd[u];e[mct].f=f;hd[u]=mct;return; 26 } 27 void insert(int u,int v,int f){ 28 add_edge(u,v,f);add_edge(v,u,0);return; 29 } 30 // 31 queue<int>q; 32 bool BFS(){ 33 for(int i=0;i<=T;i++)d[i]=0; 34 d[S]=1; q.push(S); 35 while(!q.empty()){ 36 int u=q.front();q.pop(); 37 for(int i=hd[u];i;i=e[i].nxt){ 38 int v=e[i].v; 39 if(e[i].f && !d[v]){ 40 d[v]=d[u]+1; 41 q.push(v); 42 } 43 } 44 } 45 return d[T]; 46 } 47 int DFS(int u,int lim){ 48 if(u==T)return lim; 49 int f=0,tmp; 50 for(int i=hd[u];i;i=e[i].nxt){ 51 int v=e[i].v; 52 if(e[i].f && d[v]==d[u]+1 && (tmp=DFS(v,min(lim,e[i].f)))){ 53 e[i].f-=tmp; 54 e[i^1].f+=tmp; 55 lim-=tmp; 56 f+=tmp; 57 if(!lim)return f; 58 } 59 } 60 d[u]=0; 61 return f; 62 } 63 int Dinic(){ 64 int res=0; 65 while(BFS())res+=DFS(S,INF); 66 return res; 67 } 68 // 69 struct point{ 70 double x,y; 71 point(){} 72 point(double _x,double _y):x(_x),y(_y){} 73 point operator - (const point &b){return point(x-b.x,y-b.y);} 74 }lich[mxn],tr[mxn],wisp[mxn]; 75 int range[mxn],CD[mxn],R[mxn]; 76 double Cross(const point &a,const point &b){return a.x*b.y-a.y*b.x;} 77 double DT(double x){ 78 if(fabs(x)<1e-6)return 0; 79 return (x>0)?1:-1; 80 } 81 double Dist(const point &a,const point &b){ 82 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 83 } 84 int K; 85 // 86 bool check(int a,int b){ 87 double tmp=Dist(lich[a],wisp[b]); 88 if(tmp+1e-6>(double)range[a])return 0; 89 for(int i=1;i<=K;i++){ 90 double res=Cross(wisp[b]-lich[a],tr[i]-lich[a]); 91 if(DT(res)==0){ 92 if(Dist(lich[a],wisp[b])+R[i]<max(Dist(lich[a],tr[i]),Dist(wisp[b],tr[i])))return 0; 93 continue; 94 } 95 else{ 96 double h=fabs(res)/tmp; 97 if(h+1e-6<R[i])return 0; 98 } 99 } 100 return 1; 101 } 102 // 103 vector<int>ve[mxn]; 104 bool vis[mxn]; 105 void Build(int lim){ 106 memset(hd,0,sizeof hd);mct=1; 107 int i,j; 108 for(i=1;i<=m;i++)insert(S,i,1); 109 for(i=1;i<=n;i++)insert(m+i,T,lim/CD[i]+1); 110 for(i=1;i<=n;i++) 111 for(j=0;j<ve[i].size();j++) 112 insert(ve[i][j],m+i,1); 113 return; 114 } 115 void solve(){ 116 S=0;T=n+m+1; 117 int l=0,r=1e7,ans=INF; 118 while(l<=r){ 119 int mid=(l+r)>>1; 120 Build(mid); 121 int tmp=Dinic(); 122 if(tmp==m){ 123 ans=mid;r=mid-1; 124 }else l=mid+1; 125 } 126 printf("%d\n",ans); 127 return; 128 } 129 // 130 131 int main(){ 132 // freopen("in.txt","r",stdin); 133 int i,j; 134 n=read();m=read();K=read(); 135 for(i=1;i<=n;i++){ 136 lich[i].x=read();lich[i].y=read(); 137 range[i]=read();CD[i]=read(); 138 } 139 for(i=1;i<=m;i++){ 140 wisp[i].x=read();wisp[i].y=read(); 141 } 142 for(i=1;i<=K;i++){tr[i].x=read();tr[i].y=read();R[i]=read();} 143 for(i=1;i<=n;i++) 144 for(j=1;j<=m;j++) 145 if(check(i,j)){ 146 ve[i].push_back(j); 147 vis[j]=1; 148 } 149 for(i=1;i<=m;i++){ 150 if(!vis[i]){ 151 printf("-1\n"); 152 return 0; 153 } 154 } 155 solve(); 156 return 0; 157 }
本文为博主原创文章,转载请注明出处。