码迷,mamicode.com
首页 > 其他好文 > 详细

[DLX重复覆盖] hdu 3656 Fire station

时间:2015-07-21 12:58:45      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:

题意:

N个点,再点上建M个消防站。

问消防站到每个点的最大距离的最小是多少。

思路:

DLX直接二分判断TLE了。

这时候一个很巧妙的思路

我们求的距离一定是两个点之间的距离

因此我们把距离都求一遍排序一下。

然后用下标二分  这样就AC了。

代码:

#include"stdio.h"
#include"algorithm"
#include"string.h"
#include"iostream"
#include"cmath"
#include"queue"
#include"map"
#include"vector"
#include"string"
using namespace std;
#define eps 1e-6
#define N 55*55
#define RN 55
#define CN 55
double dist[N];
int kx;
struct DLX
{
    int n,m,C;
    int U[N],D[N],L[N],R[N],Row[N],Col[N];
    int H[RN],S[CN],cnt,ans[RN];
    void init(int _n,int _m)
    {
        n=_n;
        m=_m;
        for(int i=0; i<=m; i++)
        {
            S[i]=0;
            U[i]=D[i]=i;
            L[i]=(i==0?m:i-1);
            R[i]=(i==m?0:i+1);
        }
        C=m;
        for(int i=1; i<=n; i++) H[i]=-1;
    }
    void link(int x,int y)
    {
        C++;
        Row[C]=x;
        Col[C]=y;
        S[y]++;
        U[C]=U[y];
        D[C]=y;
        D[U[y]]=C;
        U[y]=C;
        if(H[x]==-1) H[x]=L[C]=R[C]=C;
        else
        {
            L[C]=L[H[x]];
            R[C]=H[x];
            R[L[H[x]]]=C;
            L[H[x]]=C;
        }
    }
    void del(int x)
    {
        for(int i=D[x]; i!=x; i=D[i])
        {
            R[L[i]]=R[i];
            L[R[i]]=L[i];
        }
    }
    void rec(int x)
    {
        for(int i=U[x]; i!=x; i=U[i])
        {
            R[L[i]]=i;
            L[R[i]]=i;
        }
    }
    int used[CN];
    int h()
    {
        int sum=0;
        for(int i=R[0]; i!=0; i=R[i]) used[i]=0;
        for(int i=R[0]; i!=0; i=R[i])
        {
            if(used[i]==0)
            {
                sum++;
                used[i]=1;
                for(int j=D[i]; j!=i; j=D[j]) for(int k=R[j]; k!=j; k=R[k]) used[Col[k]]=1;
            }
        }
        return sum;
    }
    int dance(int x)
    {
        if(x+h()>=cnt || x+h()>kx) return 0;
        if(R[0]==0)
        {
            cnt=min(cnt,x);
            if(cnt<=kx) return 1;
            return 0;
        }
        int now=R[0];
        for(int i=R[0]; i!=0; i=R[i])
        {
            if(S[i]<S[now])
                now=i;
        }
        for(int i=D[now]; i!=now; i=D[i])
        {
            del(i);
            for(int j=R[i]; j!=i; j=R[j]) del(j);
            if (dance(x+1)) return 1;
            for(int j=L[i]; j!=i; j=L[j]) rec(j);
            rec(i);
        }
        return 0;
    }
} dlx;
struct node
{
    double x,y;
} dian[55];
double dis(double x1,double y1,double x2,double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        scanf("%d%d",&n,&kx);
        for(int i=1;i<=n;i++) scanf("%lf%lf",&dian[i].x,&dian[i].y);
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                dist[cnt++]=dis(dian[i].x,dian[i].y,dian[j].x,dian[j].y);
            }
        }
        sort(dist,dist+cnt);
        int l=0,r=cnt-1;
        double ans;
        while(l<=r)
        {
            int mid=(l+r)/2;
            dlx.init(n,n);
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    double tep=dis(dian[i].x,dian[i].y,dian[j].x,dian[j].y);
                    if(tep>dist[mid]) continue;
                    dlx.link(i,j);
                }
            }
            dlx.cnt=999;
            if(dlx.dance(0))
            {
                ans=dist[mid];
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%.6f\n",ans);

    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

[DLX重复覆盖] hdu 3656 Fire station

标签:

原文地址:http://blog.csdn.net/wdcjdtc/article/details/46981985

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!