hdu2295 Radar 二分+DLX重复覆盖+A*

来源:互联网 发布:电脑自动分区软件 编辑:程序博客网 时间:2024/05/17 07:48

      N个城市,M个雷达站,最多可开K个雷达工作,给出城市和雷达的坐标,问雷达的工作半径最少为多少可以满足要求?

直接二分距离,判断当前距离K个雷达站是否能覆盖全部城市,判断的时候可以用DLX来搜,建立M行*N列的01矩阵,行表示雷达站,列表示城市,由于允许多个雷达站覆盖一个城市的情况,所以这题跟精确覆盖的实现还不太一样,remove和resume要改一下。另外这题裸上还会TLE,所以在搜索的时候要加个A*剪枝,估价函数的含义大致就是在当前的状态下,最少需要多少行才有可能覆盖所有的城市(注意这个数只是个下界,不是确定的值),那么若当前启动的雷达数+估价超过了限制的话,就可以剪掉了...

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>using namespace std;typedef long long ll;const int maxr=55;const int maxc=55;const int maxn=maxr*maxc;const int inf=(1<<28);int col[maxn],row[maxn],ans[maxn];int S[maxc],H[maxr];int size,cnt;int U[maxn],D[maxn],L[maxn],R[maxn];int g[maxr][maxc];struct PT{    double x,y;}city[55],radar[55];int n,m,k;struct DLX{    int h()    {        bool hs[55];        memset(hs,0,sizeof hs);        int ret=0;        for (int i=R[0]; i!=0; i=R[i])        {            if (!hs[i])            {                ret++;                hs[i]=true;                for (int j1=D[i]; j1!=i; j1=D[j1])                 for (int j2=R[j1]; j2!=j1; j2=R[j2])                 hs[col[j2]]=true;            }        }        return ret;    }    void remove(int c)    {        for (int i=D[c]; i!=c; i=D[i])         {             L[R[i]]=L[i];             R[L[i]]=R[i];         }    }    void resume(int c)    {        for (int i=U[c]; i!=c; i=U[i])         {             L[R[i]]=i;             R[L[i]]=i;         }    }    bool dfs(int p)    {        if (p+h()>k) return false;        if (p>k) return false;        int c=R[0];        if (c==0)        {            cnt=p;            return true;        }        for (int i=R[0]; i!=0; i=R[i])        if (S[i]<S[c]) c=i;        for (int i=D[c]; i!=c; i=D[i])        {            remove(i);            for (int j=R[i]; j!=i; j=R[j]) remove(j);            if (dfs(p+1)) return true;            for (int j=L[i]; j!=i; j=L[j]) resume(j);            resume(i);        }        return false;    }    void init(int m)    {        for (int i=0; i<=m; i++)        {            S[i]=0;            R[i]=i+1;            L[i]=i-1;            U[i]=D[i]=i;        }        L[0]=m;        R[m]=0;        size=m+1;        memset(H,-1,sizeof H);    }    void link(int x,int y)    {        ++S[col[size]=y];        row[size]=x;        D[size]=D[y];        U[D[y]]=size;        U[size]=y;        D[y]=size;        if (H[x]<0) H[x]=L[size]=R[size]=size;        else        {            R[size]=R[H[x]];            L[R[H[x]]]=size;            L[size]=H[x];            R[H[x]]=size;        }        size++;    }}dlx;double dis(PT p, PT q){    return sqrt((double)((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y)));}void init(double limit){    memset(g,false,sizeof g);    for (int i=1; i<=m; i++)     for (int j=1; j<=n; j++)     if (dis(radar[i],city[j])<=limit) g[i][j]=true;}int main(){//    freopen("in.txt","r",stdin);    int tt;    scanf("%d",&tt);    while (tt--)    {        scanf("%d%d%d",&n,&m,&k);        for (int i=1; i<=n; i++)        scanf("%lf%lf",&city[i].x,&city[i].y);        for (int i=1; i<=m; i++)        scanf("%lf%lf",&radar[i].x,&radar[i].y);        double l=0.0,r=sqrt(1000.0*1000.0*2.0);        double mid;        while(fabs(l-r)>1e-8)        {            mid=(l+r)/2.0;            init(mid);            dlx.init(n);            for (int i=1; i<=m; i++)             for (int j=1; j<=n; j++)             if (g[i][j]) dlx.link(i,j);            cnt=inf;            if (dlx.dfs(0)) r=mid;            else l=mid;        }        printf("%.6lf\n",l);    }    return 0;}


0 0
原创粉丝点击