• 【ABC181】F


    题目

    题目链接:https://atcoder.jp/contests/abc181/tasks/abc181_f
    有一个 (200 imes 2 imes 10^9) 的网格,其中横坐标区间为 ([-100,100]),纵坐标区间为 ([-10^9,10^9])。平面上有若干个点。
    你有一个圆,最开始在 ((0,-10^9)),询问圆半径最大是多少使得它可以在不接触点的情况下圆心到达 ((0,10^9))

    思路

    二分圆的直径,如果两个点之间的距离小于直径,那么显然圆没法从这两个点之间经过。注意要把直线 (x=100)(x=-100) 也看做一个点。
    那么如果连完线之后把直线 (x=100)(x=-100) 联通,那么相当于存在若干连线将左右两边隔开,这样圆就无法过去。否则可以到达。
    用并查集维护即可。
    时间复杂度 (O(n^2log k))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=110;
    const double eps=1e-5;
    int n,S,T,X[N],Y[N],father[N];
    
    int getdis(int i,int j)
    {
    	return (X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]);
    }
    
    int find(int x)
    {
    	return x==father[x]?x:father[x]=find(father[x]);
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    		scanf("%d%d",&X[i],&Y[i]);
    	S=n+1; T=n+2;
    	double l=0,r=200,mid;
    	while (r-l>=eps)
    	{
    		mid=(l+r)/2.0;
    		for (int i=1;i<=T;i++) father[i]=i;
    		for (int i=1;i<=n;i++)
    			for (int j=i+1;j<=n;j++)
    				if (getdis(i,j)<mid*mid) father[find(i)]=find(j);
    		for (int i=1;i<=n;i++)
    		{
    			if (100+Y[i]<mid) father[find(i)]=find(S);
    			if (100-Y[i]<mid) father[find(i)]=find(T);
    		}
    		if (find(S)!=find(T)) l=mid;
    			else r=mid; 
    	}
    	printf("%0.10lf
    ",l/2.0);
    	return 0;
    }
    
  • 相关阅读:
    CF238B Boring Partition
    CF1424G Years
    CF995D Game
    CF468C Hack it!
    CF1417A Copy-paste
    CF1417B Two Arrays
    CF849B Tell Your World
    [洛谷P3389][模板]高斯消元法
    CF1225D
    P6687
  • 原文地址:https://www.cnblogs.com/stoorz/p/13912595.html
Copyright © 2020-2023  润新知