zoukankan      html  css  js  c++  java
  • BZOJ1822: [JSOI2010]Frozen Nova 冷冻波

    BZOJ1822: [JSOI2010]Frozen Nova 冷冻波

    https://lydsy.com/JudgeOnline/problem.php?id=1822

    分析:

    • 二分答案,将能打到的巫妖和小精灵连边,最大流判断是否可行。
    • 重点在于连边,即判断线段和圆是否有交。
    • 转化成点到线段的最短距离。
    • 我们先判断那两个角是否是钝角,这里我的做法是直接用atan2(点积,叉积)把角求了出来。
    • 实际上因为点积是(cos),直接求点积正负就可以了。
    • 如果是钝角,则距离为到两个端店距离的min,否则用三角形面积算。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #include <cmath>
    using namespace std;
    #define N 450
    #define inf 0x3f3f3f3f
    #define M 500050
    typedef double f2;
    const f2 pi = acos(-1);
    const int S=448,T=449;
    int head[N],to[M],nxt[M],flow[M],cnt=1,Q[N],dep[N];
    int mxflow,is[N][N];
    inline void add(int u,int v,int f) {
    	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f;
    	to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0;
    }
    bool bfs() {
    	int l=0,r=0;
    	memset(dep,0,sizeof(dep)); 
    	Q[r++]=S; dep[S]=1;
    	while(l<r) {
    		int x=Q[l++],i;
    		for(i=head[x];i;i=nxt[i]) if(!dep[to[i]]&&flow[i]) {
    			dep[to[i]]=dep[x]+1; if(to[i]==T) return 1;
    			Q[r++]=to[i];
    		}
    	}return 0;
    }
    int dfs(int x,int mf) {
    	int nf=0,i;
    	if(x==T) return mf;
    	for(i=head[x];i;i=nxt[i]) if(dep[to[i]]==dep[x]+1&&flow[i]) {
    		int tmp=dfs(to[i],min(mf-nf,flow[i]));
    		if(!tmp) dep[to[i]]=0;
    		nf+=tmp; flow[i]-=tmp; flow[i^1]+=tmp;
    		if(nf==mf) break;
    	}
    	return nf;
    }
    void dinic() {
    	mxflow=0; int f;
    	while(bfs()) {
    		while((f=dfs(S,inf))) mxflow+=f;
    	}
    }
    struct Point {
    	int x,y;
    	Point() {}
    	Point(int x_,int y_) {x=x_,y=y_;}
    	Point operator - (const Point &p) const {return Point(x-p.x,y-p.y);}
    }a[N],b[N];
    int pf(int x) {return x*x;}
    int dis(const Point &p1,const Point &p2) {return pf(p1.x-p2.x)+pf(p1.y-p2.y);}
    f2 dot(const Point &p1,const Point &p2) {return p1.x*p2.x+p1.y*p2.y;}
    f2 cross(const Point &p1,const Point &p2) {return p1.x*p2.y-p1.y*p2.x;}
    f2 angle(const Point &p1,const Point &p2,const Point &p3) {return atan2(dot(p2-p1,p3-p1),cross(p2-p1,p3-p1));}
    struct Circle {
    	Point p; int r;
    }c[N];
    int rr[N],tt[N],n,m,K;
    bool check(int x,int y,int z) {
    	Point p1=a[x],p2=b[y],p3=c[z].p;
    	f2 d=abs(cross(p3-p1,p2-p1)/sqrt(dis(p1,p2))); int r=c[z].r;
    	if(d>c[z].r) return 0;
    	if(dis(p1,p3)<=r*r||dis(p2,p3)<=r*r) return 1;
    	return angle(p3,p1,p2)<pi/2&&angle(p3,p2,p1)<pi/2;	
    }
    int main() {
    	scanf("%d%d%d",&n,&m,&K);
    	int i,j,k;
    	for(i=1;i<=n;i++) scanf("%d%d%d%d",&a[i].x,&a[i].y,&rr[i],&tt[i]);
    	for(i=1;i<=m;i++) scanf("%d%d",&b[i].x,&b[i].y);
    	for(i=1;i<=K;i++) scanf("%d%d%d",&c[i].p.x,&c[i].p.y,&c[i].r);
    	for(i=1;i<=n;i++) {
    		for(j=1;j<=m;j++) if(dis(a[i],b[j])<=rr[i]*rr[i]) {
    			int flg=1;
    			for(k=1;k<=K;k++) if(check(i,j,k)) {flg=0; break;}
    			is[i][j]=flg;
    		}
    	}
    	int l=0,r=inf;
    	while(l<r) {
    		int mid=(l+r)>>1;
    		memset(head,0,sizeof(head)); cnt=1;
    		for(i=1;i<=n;i++) add(S,i,mid/tt[i]+1);
    		for(i=1;i<=m;i++) add(i+n,T,1);
    		for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(is[i][j]) add(i,j+n,1);
    		dinic();
    		if(mxflow==m) r=mid;
    		else l=mid+1;
    	}
    	printf("%d
    ",l==inf?-1:l);
    }
    
  • 相关阅读:
    Linux程序调试GDB——数据查看
    linux C++ 共享库导出类
    MyBatis 通用Mapper接口 Example的实例
    mybatis3 @SelectProvider
    Maven命令行使用 mvn clean package
    Springboot IDEA eclipse 打包
    Intellij IDEA Debug
    SpringCloud之Eureka 服务注册和服务发现基础篇2
    SpringCloud组件和概念介绍1
    IntelliJ IDEA SVN
  • 原文地址:https://www.cnblogs.com/suika/p/10205524.html
Copyright © 2011-2022 走看看