zoukankan      html  css  js  c++  java
  • UVALive 6168 Fat Ninjas --二分小数+搜索

    题意:一个NxN的网格地板,有一些激光束从天花板垂直射向地面的某个网格,一个圆要安全地从左走到右,不碰到上边界,下边界以及激光束,问这个圆的直径最大能达到多大。

    分析:可以二分直径,关键在check函数的写法。可以讲这个圆缩成一个点,把圆的直径转化为激光的扫描范围,当激光范围完全堵死一条通道的时候,这个直径则是不可行的。怎样判断是否堵死一条通道了呢。每次check(dis)的时候,枚举激光束对,如果激光束之间距离小于dis,那么它们两个之间建一条边。还要注意处理边界,如果激光束范围与上边界或下边界相交,那么边界与这个激光束也建一条边。最后从一个边界dfs到另一个边界,如果能够dfs到,那么说明此时通道被堵死,此dis是不行的。继续二分就能得到答案。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <string>
    #include <vector>
    using namespace std;
    #define N 5007
    
    struct node
    {
        int x,y;
    }p[N];
    
    double d[N][N];
    vector<int> G[N];
    int n,L;
    int vis[N],S,E;
    
    double dis(node ka,node kb)
    {
        return (double)sqrt((ka.x-kb.x)*(ka.x-kb.x)+(ka.y-kb.y)*(ka.y-kb.y));
    }
    
    int dfs(int u,int fa)
    {
        if(u == E)
            return 1;
        vis[u] = 1;
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i];
            if(v == fa)
                continue;
            if(vis[v])
                continue;
            if(dfs(v,u))
                return 1;
        }
        return 0;
    }
    
    bool check(double D)
    {
        S = 0;
        E = L+1;
        for(int i=0;i<=L+1;i++)
            G[i].clear();
        for(int i=1;i<=L;i++)
        {
            if(p[i].y < D)
                G[S].push_back(i);
            if(p[i].y + D > n)
                G[i].push_back(E);
            for(int j=i+1;j<=L;j++)
            {
                if(d[i][j] < D)
                {
                    G[i].push_back(j);
                    G[j].push_back(i);
                }
            }
        }
        memset(vis,0,sizeof(vis));
        if(dfs(S,-1))
            return 0;
        return 1;
    }
    
    int main()
    {
        int i,j;
        while(scanf("%d%d",&n,&L)!=EOF && n)
        {
            for(i=1;i<=L;i++)
                scanf("%d%d",&p[i].x,&p[i].y);
            for(i=1;i<=L;i++)
                for(j=i+1;j<=L;j++)
                    d[i][j] = dis(p[i],p[j]);
            double low = eps;
            double high = n;
            while(low+eps < high)
            {
                double mid = (low+high)/2.0;
                if(check(mid))
                    low = mid;
                else
                    high = mid;
            }
            printf("%.3lf
    ",low);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    设置java.library.path的值(Mac/Linux/Windows)
    英特尔老款CPU支持虚拟化对照表(转)
    长城小主机GW1等型号进BIOS的设置方法
    Mac 10.12允许任何来源
    DDos与CC攻击的简单个人理解
    Mac 10.12下iTerm2使用lrzsz上传下载文件
    Mac 10.12连接iSCSI硬盘软件iSCSI Initiator X
    华为S5300系列交换机V100R005SPH021升级补丁
    华为S5300系列交换机V100R005SPH020升级补丁
    华为S5300系列交换机V100R006SPH019升级补丁
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3900435.html
Copyright © 2011-2022 走看看