zoukankan      html  css  js  c++  java
  • [题解] 航班通信

    本题有向量做法,但因为要不断地将位置和时间相互转化,比较麻烦。

    因为研究的对象是时间 (t),可以建立 (x, y) 关于 (t) 的参数方程,这样可以表示出任意直线。

    显然二分答案 (r),需要求出直线和点,点和点之间距离在 (r) 以内的区间,然后对于每个点暴力建图检测。

    直接解二次方程得出两个距离为 (r) 的位置,注意要特判 (Delta<0),两线平行的情况。

    然后注意处理下航线开始,结束的时间就好,写的时候要注意细节。卡了一天

    复杂度 (mathcal O(n + m)^4)

    Code

    函数 KBRSolve 求解 ((k_1t+b_1)^2 + (k_2t + b_2)^2 - r^2 = 0)

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    
    #define File(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
    template<class T> void upmax(T &x, T y){x = x>y ? x : y;}
    template<class T> void upmin(T &x, T y){x = x<y ? x : y;}
    
    const int N = 105;
    const double eps = 1e-6;
    int n, m;
    double x[N], y[N];
    double kx[N], bx[N], ky[N], by[N];
    double t1[N], t2[N];
    
    double equal(double x, double y = 0) {return fabs(x - y) < eps;}
    double sq(double x) {return x * x;}
    pair<double, double> quadSolve(double a, double b, double c){
    	if(a == 0) return {-c / b, -c / b};
    	double delta = b * b - 4 * a * c;
    	if(-1e-8 < delta && delta < 0) delta = 0;
    	if(delta < 0) return {0, -1};
    	else{
    		delta = sqrt(delta);
    		return {(-b - delta) / (2 * a), (-b + delta) / (2 * a)};
    	}
    }
    pair<double, double> KBRSolve(double k1, double b1, double k2, double b2, double r){
    	return quadSolve(
    		sq(k1) + sq(k2),
    		2 * (k1 * b1 + k2 * b2),
    		sq(b1) + sq(b2) - sq(r)
    	);
    }
    
    bool G[N][N], vis[N];
    
    void dfs(int x){
    	vis[x] = true;
    	for(int j=n+1, li=n+m; j<=li; j++)
    		if(G[x][j] && !vis[j]) dfs(j);
    }
    
    bool check(double r){
    	struct Event{
    		double t;
    		int u, v;
    		Event() {}
    		Event(double Time, int U, int V) : t(Time), u(U), v(V) {}
    	};
    	static Event ev[N * N * 2];
    	int ec = 0;
    	for(int i=1; i<=n; i++)
    		for(int j=1; j<=m; j++){
    			auto R = KBRSolve(kx[j], bx[j] - x[i], ky[j], by[j] - y[i], r);
    			if(R.first - R.second < eps){
    				upmax(R.first, t1[j]);
    				upmin(R.second, t2[j]);
    				if(R.first - R.second > -eps) continue;
    				ev[++ec] = Event(R.first, i, j + n);
    				ev[++ec] = Event(R.second, -i, -j - n);
    			}
    		}
    	for(int i=1; i<=m; i++)
    		for(int j=i+1; j<=m; j++){
    			pair<double, double> R;
    			if(equal(kx[i] * ky[j], kx[j] * ky[i])){
    				if(sqrt(sq(bx[i] - bx[j]) + sq(by[i] - by[j])) - r < eps) R = {max(t1[i], t1[j]), min(t2[i], t2[j])};
    				else R = {0, -1};
    			}
    			else R = KBRSolve(kx[j] - kx[i], bx[j] - bx[i], ky[j] - ky[i], by[j] - by[i], r);
    			if(R.first + eps < R.second){
    				upmax(R.first, max(t1[i], t1[j]));
    				upmin(R.second, min(t2[i], t2[j]));
    				if(R.first + eps > R.second) continue;
    				ev[++ec] = Event(R.first, i + n, j + n);
    				ev[++ec] = Event(R.second, -i - n, -j - n);
    			}
    		}
    	sort(ev + 1, ev + 1 + ec, [](const Event &a, const Event &b){
    		return a.t < b.t;
    	});
    	for(int i=1; i<=ec; i++){
    		int u = ev[i].u, v = ev[i].v;
    		if(u > 0) G[u][v] = G[v][u] = true;
    		else G[-u][-v] = G[-v][-u] = false;
    		fill_n(vis + 1, n + m, false);
    		for(int j=1; j<=n; j++) dfs(j);
    		for(int j=1; j<=m; j++)
    			if(t1[j] - ev[i].t < -eps && ev[i].t - t2[j] < -eps && !vis[j + n]) return false;
    	}
    	return true;
    }
    
    int main(){
    	scanf("%d%d", &n, &m);
    	for(int i=1; i<=n; i++)
    		scanf("%lf%lf", x + i, y + i);
    	for(int i=1; i<=m; i++){
    		int s, t;
    		scanf("%d%d%lf%lf", &s, &t, t1 + i, t2 + i); ++s; ++t;
    		kx[i] = (x[t] - x[s]) / (t2[i] - t1[i]);
    		bx[i] = x[s] - t1[i] * kx[i];
    		ky[i] = (y[t] - y[s]) / (t2[i] - t1[i]);
    		by[i] = y[s] - t1[i] * ky[i];
    	}
    	double l = 0, r = sqrt(2e6) / 2, mid;
    	while(r - l > 1e-5){
    		mid = (l + r) / 2;
    		if(check(mid)) r = mid;
    		else l = mid;
    	}
    	printf("%.4lf
    ", r);
    	return 0;
    }
    
  • 相关阅读:
    出现错误:代理服务器拒绝连接的解决方法
    ansible之模块 条件判断
    软件相关模块与ansible剧本
    ansible的应用
    Celery -----异步任务,定时任务,周期任务
    SQLAlchemy增删改查 一对多 多对多
    python是如何进行内存管理的?
    Django的模板层(1)
    1.Git安装
    6.case
  • 原文地址:https://www.cnblogs.com/RiverHamster/p/sol-oj4133.html
Copyright © 2011-2022 走看看