bzoj1822
1822: [JSOI2010]Frozen Nova 冷冻波
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2080 Solved: 657
[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
思路很简单的。每个witch向他能攻击到的精灵连一条容量1的边,每个精灵向T连容量1的边。
二分时间,得到witch的攻击次数。S向每个witch连接容量为攻击次数的边,判断最大流是不是=精灵个数
但是,,这道题的连边判断很蛋疼,要用很多几何知识。
代码写错了一些地方,懒得调了,先挂上
/* 爆炸 不想调了 */ #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<queue> #include<cmath> #define inf 0x3f3f3f3f #define ll long long #define N 405 using namespace std; int n,m,K,tot,S,T,pre,phd[N],hd[N],d[N],cur[N],vis[N]; struct witch{int x,y,r,t;}t[N]; struct ghost{int x,y;}p[N]; struct tree{int x,y,r;}tr[N]; struct edge{int v,next,cap;}e[N*N*2]; void adde(int u,int v,int c){ e[tot].v=v; e[tot].next=hd[u]; e[tot].cap=c; hd[u]=tot++; } bool bfs(){ queue<int>q; memset(vis,0,sizeof(vis)); d[S]=0;vis[S]=1;q.push(S); while(!q.empty()){ int u=q.front();q.pop(); for(int i=hd[u];~i;i=e[i].next){ int v=e[i].v; if(e[i].cap&&!vis[v]){ vis[v]=1; d[v]=d[u]+1; q.push(v); } } } return vis[T]; } int dfs(int u,int a){ if(u==T||!a)return a; int fl=0,f; for(int &i=cur[u];~i;i=e[i].next){ int v=e[i].v; if(e[i].cap&&d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap,a)))){ fl+=f;a-=f;e[i].cap-=f; e[i^1].cap+=f;if(!a)break; } } return fl; } int dinic(){ int flow=0; while(bfs()){ for(int i=S;i<=T;i++)cur[i]=hd[i]; flow+=dfs(S,inf); } return flow; } int calc(int i,int j) {return (p[j].x-t[i].x)*(p[j].x-t[i].x)+(p[j].y-t[i].y)*(p[j].y-t[i].y);} struct vec{ int x,y; vec res(){ vec a=*this; a.x=-a.x; a.y=-a.y; return a; } }; int dj(vec a,vec b){return a.x*b.x+a.y*b.y;} int cj(vec a,vec b){return abs(a.x*b.y-b.x*a.y);} bool check(int i,int j){ for(int k=1;k<=K;k++){ vec a=(vec){tr[k].x-t[i].x,tr[k].y-t[i].y}; vec b=(vec){p[j].x-t[i].x,p[j].y-t[i].y}; int sq=cj(a,b); double d=sqrt(calc(i,j)); double h=sq/d/2; if(h>tr[k].r)continue; if(dj(a,b)<=0)continue; a=(vec){tr[k].x-p[j].x,tr[k].y-p[j].y}; b=b.res(); if(dj(a,b)>0)return 0; } return 1; } bool judge(int x){ int sum=0; for(int i=0;i<tot;i++){ if(i<pre){ if(i&1)e[i].cap=0; else e[i].cap=1; } else{ int id=(i-pre+1)/2+1; if(i&1)e[i].cap=0; else e[i].cap=x/t[id].t+1,sum+=x/t[id].t+1; } } if(sum<m)return 0; int flow=dinic(); return flow==m; } int main(){ #ifdef wsy freopen("data.in","r",stdin); #else //freopen(".in","r",stdin); //freopen(".out","w",stdout); #endif memset(hd,-1,sizeof(hd)); scanf("%d%d%d",&n,&m,&K); S=0;T=n+m+1;int mxt; for(int i=1;i<=n;i++) scanf("%d%d%d%d",&t[i].x,&t[i].y,&t[i].r,&t[i].t),mxt=max(mxt,t[i].t); for(int i=1;i<=m;i++) scanf("%d%d",&p[i].x,&p[i].y); for(int i=1;i<=K;i++) scanf("%d%d%d",&tr[i].x,&tr[i].y,&tr[i].r); int fg=0; for(int i=1;i<=m&&!fg;i++) for(int j=1;j<=K&&!fg;j++){ int d=(p[i].x-tr[j].x)*(p[i].x-tr[j].x)+(p[i].y-tr[j].y)*(p[i].y-tr[j].y); if(d<=tr[j].r*tr[j].r)fg=1; } if(fg){puts("-1");return 0;} for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ int dis=calc(i,j); if(dis>t[i].r*t[i].r||!check(i,j))continue; adde(i,j+n,1);adde(j+n,i,0);//printf("%d %d %d\n",i,j+n,1); } for(int i=1;i<=m;i++)adde(i+n,T,1),adde(T,i+n,0)/*,printf("%d %d %d\n",i+n,T,1)*/; pre=tot;for(int i=1;i<=n;i++)adde(S,i,0),adde(i,S,0); int l=0,r=mxt*m,ans=-1; while(l<=r){ int mid=l+r>>1; if(judge(mid)){ r=mid-1; ans=mid; } else l=mid+1; } printf("%d",ans); return 0; }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。