hdu2295DLX重复覆盖+二分

题目是说 给了n个城市 m个雷达 你只能选择其中的k个雷达进行使用 你可以设置每个雷达的半径,最后使得所有城市都被覆盖,要求雷达的半径尽可能的小(所有雷达的半径是一样的)

二分最小半径,然后每次重新建立这个十字链表,跑dlx

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cmath>
using namespace std;
const int maxnode=3000;
const int maxm=55;
int K;
struct DLX
{
    int n,m,siz;
    int U[maxnode],D[maxnode],R[maxnode],L[maxnode],row[maxnode],
    col[maxnode];
    int H[maxm],S[maxm];
    int anss,ans[maxm];
    void init(int n,int m)
    {
        this->n=n;
        this->m=m;
        for(int i=0; i<=n; i++)
        {
            S[i]=0;
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
        }
        R[n]=0; L[0]=n;
        siz=n+1;
        for(int i=0; i<=m; i++)
            H[i]=-1;
    }
    void Link(int r, int c)
    {
        row[siz]=r;
        col[siz]=c;
        S[c]++;
        D[siz]=c;
        U[siz]=U[c];
        D[U[siz]]=siz;
        U[D[siz]]=siz;
        if(H[r]<0)
            {
                H[r]=L[siz]=R[siz]=siz;
            }
        else
            {
                L[siz]=H[r];
                R[siz]=R[H[r]];
                R[L[siz]]=siz;
                L[R[siz]]=siz;
                H[r]=siz;
            }
            siz++;
    }
    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]]=R[L[i]]=i;
    }
    bool v[maxnode];
    int AX()
    {
        int ret=0;
        for(int c=R[0]; c!=0; c=R[c])v[c]=true;
        for(int c=R[0]; c!=0; c=R[c])
         if(v[c])
            {
                ret++;
              v[c]=false;
              for(int i=D[c]; i!=c; i=D[i])
                for(int j=R[i]; j!=i; j=R[j])
                v[col[j]]=false;
            }
            return ret;
    }
    bool Dance(int d)
    {
        if(d+AX()>K)return false;
        if(R[0]==0)return d<=K;
        int c=R[0];
        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(Dance(d+1))return true;
            for(int j=L[i]; j!=i; j=L[j])resume(j);
            resume(i);
        }
        return false;
    }
}g;
const double eps=1e-8;
struct Point{
   int x,y;
   void input()
   {
       scanf("%d%d",&x,&y);
   }
}city[maxm],station[maxm];
double dis(Point a, Point b)
{
    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
int main()
{
     int T;
     int n,m;
     scanf("%d",&T);
     while(T--)
     {
         scanf("%d%d%d",&n,&m,&K);
         for(int i=0 ;i<n; i++)city[i].input();
         for(int i=0; i<m; i++)station[i].input();
         double l=0,r=1e8;
         while(r-l>=eps)
            {
                double mid=(l+r)/2;
               g.init(n,m);
               for(int i=0; i<m; i++)
                for(int j=0; j<n; j++)
               if(dis(station[i],city[j])<mid-eps)
                g.Link(i+1,j+1);
               if(g.Dance(0))r=mid-eps;
               else l=mid+eps;
            }
        printf("%.6lf\n",l);
     }
    return 0;
}
View Code

 

posted @ 2015-07-31 15:41  来自大山深处的菜鸟  阅读(184)  评论(0编辑  收藏  举报