• BZOJ 1822 Frozen Nova 霜冻新星


    分配问题,将小精灵分配给巫妖,巫妖可接收量取决于时间长短,适应性取决于地形

    预处理巫妖小精灵对的可行性,就是询问线段 (AB) 与圆 (O) 是否有交点

    过点 (O) 作直线 (AB) 的垂线,考虑垂足,若垂足不在线段 (AB) 上,则问题等价于线段是否存在一段点在圆内

    否则通过 (overrightarrow{AO} ast overrightarrow{AB}) 计算 (overrightarrow{AO}), (overrightarrow{AB}) 所夹平行四边形面积,进而求得 (O) 到直线 (AB) 的距离,与半径比较大小即可

    列出式子整理一下就可以避免double了!还有不要忘了巫妖有攻击半径

    二分时间,用网络流判断可行性,即

    由源点向巫妖连施法次数的边,巫妖向小精灵连边,小精灵连向汇点

    二分上界为 (MaxTast M) ,下界为 (0) ,最大流等于小精灵数即为可行

    #include <cstdio>
    #include <algorithm>
    
    using std::min;
    using std::max;
    
    const int MAXN=211;
    const int MAXM=211;
    const int MAXK=211;
    const int MAXV=MAXN+MAXM;
    const int MAXE=MAXN*MAXM+MAXN+MAXM;
    const int INF=1034567890;
    
    int N, M, K;
    bool Win=true;
    
    struct Pos{
    	int x, y;
    	Pos(){}
    	Pos(int _x, int _y){x=_x;y=_y;}
    	void read(){
    		scanf("%d%d", &x, &y);
    	}
    };
    
    Pos operator - (Pos A, Pos B){
    	return Pos(A.x-B.x, A.y-B.y);
    }
    
    int Len(Pos A){
    	return A.x*A.x+A.y*A.y;
    }
    
    int Dis(Pos A, Pos B){
    	return Len(A-B);
    }
    
    int corss(Pos A, Pos B){
    	return A.x*B.y-A.y*B.x;
    }
    
    int dot(Pos A, Pos B){
    	return A.x*B.x+A.y*B.y;
    }
    
    struct Elf{
    	Pos P;
    	bool OutofTree;
    	bool Link;
    } El[MAXM];
    
    struct Lich{
    	Pos P;
    	int R, T;
    	bool OutofTree;
    } L[MAXN];
    
    struct Tree{
    	Pos P;
    	int R;
    } T[MAXK];
    
    bool Map[MAXN][MAXM];
    
    struct Vert{
    	int FE;
    	int Bfn, Lev;
    } V[MAXV];
    
    int Vcnt;
    int Lp[MAXN], Ep[MAXM];
    int Sour, Sink;
    
    struct Edge{
    	int x, y, f, next, neg;
    } E[MAXE<<1];
    
    int Ecnt;
    
    void addE(int a, int b, int c=1){
    	++Ecnt;
    	E[Ecnt].x=a;E[Ecnt].y=b;E[Ecnt].f=c;E[Ecnt].next=V[a].FE;V[a].FE=Ecnt;E[Ecnt].neg=Ecnt+1;
    	++Ecnt;
    	E[Ecnt].y=a;E[Ecnt].x=b;E[Ecnt].f=0;E[Ecnt].next=V[b].FE;V[b].FE=Ecnt;E[Ecnt].neg=Ecnt-1;
    }
    
    int Q[MAXV], Head, Tail;
    int BFN;
    
    bool BFS(int at=Sour){
    	Head=Tail=1;++BFN;
    	V[at].Lev=1;
    	Q[Tail++]=at;
    	V[at].Bfn=BFN;
    	while(Head<Tail){
    		at=Q[Head++];
    		for(int k=V[at].FE, to;k>0;k=E[k].next){
    			if(E[k].f<=0)	continue;
    			to=E[k].y;
    			if(V[to].Bfn==BFN)	continue;
    			V[to].Lev=V[at].Lev+1;
    			Q[Tail++]=to;
    			V[to].Bfn=BFN;
    		}
    	}
    	return V[Sink].Bfn==BFN;
    }
    
    int DFS(int at=Sour, int inc=INF){
    	if(at==Sink || inc<=0)	return inc;
    	int ret=0, out;
    	for(int k=V[at].FE, to;k>0;k=E[k].next){
    		if(E[k].f<=0)	continue;
    		to=E[k].y;
    		if(V[to].Lev!=V[at].Lev+1)	continue;
    		out=DFS(to, min(E[k].f, inc));
    		ret+=out;inc-=out;
    		E[k].f-=out;E[E[k].neg].f+=out;
    	}
    	if(inc>0)	V[at].Lev=-1;
    	return ret;
    }
    
    int DINIC(){
    	int ret=0;
    	while(BFS()){
    		ret+=DFS();
    	}
    	return ret;
    }
    
    int Left, Right, Mid;
    int MaxT;
    
    int Cnt(Lich &l, int &t){
    	if(l.T==0)	return INF;
    	return t/(l.T)+1;
    }
    
    bool Test(int Time){
    	for(int i=1;i<=Vcnt;++i)	V[i].FE=0;
    	Ecnt=0;
    	for(int i=1;i<=N;++i)	addE(Sour, Lp[i], Cnt(L[i], Time));
    	for(int i=1;i<=M;++i)	addE(Ep[i], Sink);
    	for(int i=1;i<=N;++i)
    		for(int j=1;j<=M;++j)
    			if(Map[i][j])
    				addE(Lp[i], Ep[/*i*/j]);
    	return DINIC()==M;
    }
    
    int main(){
    	
    	scanf("%d%d%d", &N, &M, &K);
    	for(int i=1;i<=N;++i){
    		L[i].P.read();
    		scanf("%d%d", &L[i].R, &L[i].T);
    	}
    	for(int i=1;i<=M;++i)
    		El[i].P.read();
    	for(int i=1;i<=K;++i){
    		T[i].P.read();
    		scanf("%d", &T[i].R);
    	}
    	
    	for(int i=1;i<=N;++i){
    		L[i].OutofTree=true;
    		for(int j=1;j<=K;++j)
    			if(Dis(L[i].P, T[j].P)<=T[j].R*T[j].R)
    				L[i].OutofTree=false;
    	}
    	
    	for(int i=1;i<=M;++i){
    		El[i].OutofTree=true;
    		for(int j=1;j<=K;++j){
    			if(Dis(El[i].P, T[j].P)<=T[j].R*T[j].R)
    				El[i].OutofTree=false;
    		}
    	}
    	
    	for(int i=1;i<=M;++i)
    		if(!El[i].OutofTree){
    			Win=false;
    			break;
    		}
    	
    	if(!Win){
    		puts("-1");
    		return 0;
    	}
    	
    	for(int i=1;i<=N;++i){
    		if(!L[i].OutofTree)	continue;
    		for(int j=1, c;j<=M;++j){
    			if(!El[j].OutofTree)	continue;
    			if(Dis(El[j].P, L[i].P)>L[i].R*L[i].R)	continue;
    			c=1;
    			for(int k=1, Dot, Corss;k<=K && c>0;++k){
    				Dot=dot(El[j].P-L[i].P, T[k].P-L[i].P);
    				if(Dot>0 && Dot<Dis(L[i].P, El[j].P)){
    					Corss=corss(El[j].P-L[i].P, T[k].P-L[i].P);
    					if(1LL*Corss*Corss<=1LL*Dis(L[i].P, El[j].P)*T[k].R*T[k].R)
    						c=0;
    				}
    			}
    			if(c>0){
    				//addE(Lp[i], Ep[j]);
    				//printf("%d %d
    ", i, j);
    				Map[i][j]=true;
    				El[j].Link=true;
    			}
    		}
    	}
    	
    	for(int i=1;i<=M;++i)
    		if(!El[i].Link){
    			Win=false;
    			break;
    		}
    	
    	if(!Win){
    		puts("-1");
    		return 0;
    	}
    	
    	for(int i=1;i<=N;++i)	Lp[i]=++Vcnt;
    	for(int i=1;i<=M;++i)	Ep[i]=++Vcnt;
    	Sour=++Vcnt;Sink=++Vcnt;
    	
    	for(int i=1;i<=N;++i)	MaxT=max(MaxT, L[i].T);
    	
    	Left=0;Right=MaxT*M;
    	while(Left<Right){
    		Mid=(Left+Right)>>1;
    		if(Test(Mid))	Right=Mid;
    		else	Left=Mid+1;
    	}
    	Mid=(Left+Right)>>1;
    	
    	printf("%d
    ", Mid);
    	
    	return 0;
    }
    
    /*
    2 3 1
    -100 0 100 3
    100 0 100 5
    -100 -10
    100 10
    110 11
    5 5 10
    
    5
    
    */
    
  • 相关阅读:
    通过 WakaTime 统计你写代码的时长
    CCF 202012-3 带配额的文件系统
    1
    prometheus 获取cpu利用率
    springboot使用@data注解,减少不必要代码-lombok插件
    django官方教程部署simpleui时候发现加载不到静态文件解决办法
    echarts关系图研究01
    SpringBoot代码方式禁用Druid Monitor
    virtualbox给已有磁盘扩展容量
    centos7 ssh免密登录配置
  • 原文地址:https://www.cnblogs.com/Pickupwin/p/BZOJ1822.html
Copyright © 2020-2023  润新知