zoukankan      html  css  js  c++  java
  • BZOJ3199 SDOI2013 逃考 半平面交、最短路

    传送门


    如果我们对于每一个点能找到与其相邻的点(即不经过其他点监视范围能够直接到达其监视范围的点)和是否直接到达边界,就可以直接BFS求最短路求出答案。

    所以当前最重要的问题是如何找到对于每一个点相邻的点。

    如果你知道泰森多边形,你就可以发现所有点的监视范围刚好对应这些点在这个矩形里的泰森多边形。

    因为两个点监视范围的分界线一定在这两个点对应线段的中垂线上,所以将当前点到所有点的中垂线拿出来跑一遍半平面交,如果某个点与当前点的中垂线在半平面交中,那么这两个点就相邻。

    还需要知道对于某个点能否不经过其他点的监视范围到达边界,这只需要在求半平面交的时候将矩形的四边也加上就可以了。

    时间复杂度(O(TN^2logN)),可能需要轻微的常数优化。

    写计算几何的时候务必注意细节,否则可能因为把(xy)坐标打反等小错误调很久QAQ

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    //This code is written by Itst
    using namespace std;
    
    #define ld long double
    const ld eps = 1e-12;
    bool cmp(ld a , ld b){return a - eps < b && a + eps > b;}
    
    struct comp{
    	ld x , y , dir;
    	comp(ld _x = 0 , ld _y = 0) : x(_x) , y(_y){dir = atan2(y , x);}
    	comp operator +(comp a){return comp(x + a.x , y + a.y);}
    	comp operator -(comp a){return comp(x - a.x , y - a.y);}
    	comp operator *(ld a){return comp(x * a , y * a);}
    	ld operator *(comp a){return x * a.x + y * a.y;}
    	ld operator %(comp a){return x * a.y - y * a.x;}
    	bool operator <(const comp a)const{return dir < a.dir;}
    	bool operator ==(const comp a)const{return cmp(dir , a.dir);}
    }now[607];
    
    struct line{
    	comp pos , dir;
    	int ind;
    	line(comp a = comp(0,0) , comp b = comp(0,0) , int id = 0) : pos(a) , dir(b) , ind(id){}
    	bool operator <(const line a)const{return dir < a.dir || dir == a.dir && ((comp)a.pos - pos) % dir > 0;}
    }cur[607];
    
    struct Edge{
    	int end , upEd;
    }Ed[370007];
    int head[607] , que[607];
    int cntEd , N , X0 , Y0 , X1 , Y1 , hd , tl , T;
    bool mrk[607] , vis[607];
    
    inline void addEd(int a , int b){
    	Ed[++cntEd] = (Edge){b , head[a]};
    	head[a] = cntEd;
    }
    
    comp rot(comp a){
    	ld Cos = 0 , Sin = 1;
    	return comp(a.x * Cos - a.y * Sin , a.x * Sin + a.y * Cos);
    }
    
    comp intersect(line a , line b){
    	ld t = (b.dir % (a.pos - b.pos)) / (a.dir % b.dir);
    	return a.pos + a.dir * t;
    }
    
    bool chk(line a , line b , line c){
    	return (intersect(a , b) - c.pos) % c.dir > 0;
    }
    
    void create(int x){
    	int cnt = 0;
    	cur[++cnt] = line(comp(0 , 0) , comp(1 , 0));
    	cur[++cnt] = line(comp(X1 , 0) , comp(0 , 1));
    	cur[++cnt] = line(comp(X1 , Y1) , comp(-1 , 0));
    	cur[++cnt] = line(comp(0 , Y1) , comp(0 , -1));
    	for(int i = 1 ; i <= N ; ++i)
    		if(i != x)
    			cur[++cnt] = line((now[i] + now[x]) * 0.5 , rot(now[i] - now[x]) , i);
    	sort(cur + 1 , cur + cnt + 1);
    	hd = tl = que[1] = 1;
    	for(int i = 2 ; i <= cnt ; ++i){
    		if(cur[i].dir == cur[i - 1].dir) continue;
    		while(hd < tl && chk(cur[que[tl]] , cur[que[tl - 1]] , cur[i]))
    			--tl;
    		while(hd < tl && chk(cur[que[hd]] , cur[que[hd + 1]] , cur[i]))
    			++hd;
    		que[++tl] = i;
    	}
    	while(hd < tl && chk(cur[que[tl]] , cur[que[tl - 1]] , cur[que[hd]]))
    		--tl;
    	while(hd <= tl){
    		if(!cur[que[hd]].ind) mrk[x] = 1;
    		else addEd(cur[que[hd]].ind , x);
    		++hd;
    	}
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("in","r",stdin);
    	//freopen("out","w",stdout);
    #endif
    	ios::sync_with_stdio(0);
    	for(cin >> T ; T ; --T){
    		cntEd = 0;
    		memset(mrk , 0 , sizeof(mrk));
    		memset(vis , 0 , sizeof(vis));
    		memset(head , 0 , sizeof(head));
    		cin >> N >> X1 >> Y1 >> X0 >> Y0;
    		if(!N){cout << "0
    "; continue;}
    		for(int i = 1 ; i <= N ; ++i)
    			cin >> now[i].x >> now[i].y;
    		for(int i = 1 ; i <= N ; ++i)
    			create(i);
    		queue < int > q;
    		ld minDis = 1e18;
    		int minInd = 0;
    		for(int i = 1 ; i <= N ; ++i){
    			ld dis = sqrt((now[i].x - X0) * (now[i].x - X0) + (now[i].y - Y0) * (now[i].y - Y0));
    			if(dis < minDis){minDis = dis; minInd = i;}
    		}
    		vis[minInd] = 1;
    		q.push(minInd);
    		bool f = 0;
    		for(int i = 1 ; !f ; ++i){
    			for(int j = q.size() ; !f && j ; --j){
    				int t = q.front(); q.pop();
    				if(mrk[t]){f = 1; continue;}
    				for(int i = head[t] ; i ; i = Ed[i].upEd)
    					if(!vis[Ed[i].end]){
    						vis[Ed[i].end] = 1;
    						q.push(Ed[i].end);
    					}
    			}
    			if(f) cout << i << endl;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Vue 2.x windows环境下安装
    VSCODE官网下载缓慢或下载失败 解决办法
    angular cli 降级
    Win10 VS2019 设置 以管理员身份运行
    XSHELL 连接 阿里云ECS实例
    Chrome浏览器跨域设置
    DBeaver 执行 mysql 多条语句报错
    DBeaver 连接MySql 8.0 报错 Public Key Retrieval is not allowed
    DBeaver 连接MySql 8.0报错 Unable to load authentication plugin 'caching_sha2_password'
    Linux系统分区
  • 原文地址:https://www.cnblogs.com/Itst/p/10479442.html
Copyright © 2011-2022 走看看