Bzoj1822:[JSOI2010]Frozen Nova 冷冻波:计算几何+网络流

来源:互联网 发布:手机淘宝评价怎么晒图 编辑:程序博客网 时间:2024/04/29 00:00

题目链接:[JSOI2010]Frozen Nova 冷冻波

二分答案,把最优性问题转换为判定性问题

对于判断树木是否与线段相交,分两种情况讨论:

1:圆心作线段的垂线垂足不在线段上

2:圆心作线段的垂线垂足在线段上

对于1,直接比较圆心与线段两个端点距离的最小值是否小于半径

对于2,算出垂线长度后比较

区分1、2两种情况用点积即可,相当于间接判断cos的值得正负

#include<cmath>#include<queue>#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;const int maxn=251;const int inf=0x7fffffff/3;struct Lich{double x,y,r;int t;}l[maxn];struct point{double x,y;};struct Spirit{double x,y;}spr[maxn];struct Tree{double x,y,r;}t[maxn];struct edge{int to,next,w;}G[maxn*maxn*2];int tot=0,n,m,tr,h[10000],vis[10000],mx=0;int S,T,cur[10000],mp[maxn][maxn],mark[maxn];void add(int x,int y,int z){G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;G[++tot].to=x;G[tot].next=h[y];h[y]=tot;G[tot].w=0;}double powe(double x){return x*x;}double qdis(Lich a,Spirit b){return sqrt(powe(a.x-b.x)+powe(a.y-b.y));}double qdis2(double a,double b,double c,double d){return sqrt(powe(a-c)+powe(b-d));}double cross(point a,point b,point c){double x1=b.x-a.x,y1=b.y-a.y;double x2=c.x-a.x,y2=c.y-a.y;return x1*y2-x2*y1;}double dot(point a,point b,point c){    double x1=b.x-a.x,y1=b.y-a.y;double x2=c.x-a.x,y2=c.y-a.y;return x1*x2+y1*y2;}bool in_cir(Lich a,Spirit b,Tree c){point tmp1,tmp2,tmp3;tmp1=(point){a.x,a.y};tmp2=(point){b.x,b.y};tmp3=(point){c.x,c.y};if (dot(tmp3,tmp1,tmp2)>=0) return min(qdis2(a.x,a.y,c.x,c.y),qdis2(b.x,b.y,c.x,c.y))<=c.r;else return abs(cross(tmp1,tmp3,tmp2))/qdis(a,b)<=c.r;}bool bfs(){for (int i=S;i<=T;++i) vis[i]=-1;queue<int>q; q.push(S); vis[S]=0;while (!q.empty()){int u=q.front(); q.pop();for (int i=h[u];i;i=G[i].next){int v=G[i].to;if (vis[v]==-1&&G[i].w)    vis[v]=vis[u]+1,q.push(v);}}return vis[T]!=-1;}int dfs(int x,int f){if (!f||x==T) return f;int w,used=0;for (int i=cur[x];i;i=G[i].next)    if (vis[G[i].to]==vis[x]+1){w=f-used;w=dfs(G[i].to,min(w,G[i].w));G[i].w-=w; G[i^1].w+=w;used+=w; if (G[i].w) cur[x]=i;if (used==f) return used;    }if (!used) vis[x]=-1;return used;}int dinic(){int ret=0;while(bfs()){for (int i=S;i<=T;++i) cur[i]=h[i];ret+=dfs(S,inf);}return ret;}bool check(int x){tot=1;for (int i=S;i<=T;++i) h[i]=0;for (int i=1;i<=n;++i){int tmp=x/l[i].t+1;add(S,i,tmp);}for (int i=1;i<=n;++i)    for (int j=1;j<=m;++j)        if (mp[i][j]) add(i,j+n,1);for (int i=1;i<=m;++i) add(i+n,T,1);int sum=dinic();return sum==m;}void solve(){int l=0,r=m*mx,ans=inf;while (l<=r){int mid=(l+r)>>1;if (check(mid)) r=mid-1,ans=min(ans,mid);else l=mid+1;}printf("%d\n",ans==inf?-1:ans);}int main(){scanf("%d%d%d",&n,&m,&tr);S=0; T=n+m+1;for (int i=1;i<=n;++i) scanf("%lf%lf%lf%d",&l[i].x,&l[i].y,&l[i].r,&l[i].t);for (int i=1;i<=n;++i) mx=max(mx,l[i].t);for (int i=1;i<=m;++i) scanf("%lf%lf",&spr[i].x,&spr[i].y);for (int i=1;i<=tr;++i) scanf("%lf%lf%lf",&t[i].x,&t[i].y,&t[i].r);for (int i=1;i<=n;++i)    for (int j=1;j<=m;++j){double dist=qdis(l[i],spr[j]);if (dist>l[i].r) continue;bool flag=1;for (int k=1;k<=tr;++k)    if(in_cir(l[i],spr[j],t[k])){flag=0;break;}if (flag) mp[i][j]=1,mark[j]=1;    }for (int i=1;i<=m;++i)if (!mark[i]){printf("-1");return 0;}solve();}



2 0
原创粉丝点击