HDU+2295+Dancing+link++++二分

# include<stdio.h>
 # include<string.h>
 # include<cmath>
 # define N 60
 # define V N*N
 int L[V],R[V];//记录左右方向的双向链表
 int U[V],D[V];//记录上下方向的双向链表
 int C[V];//指向其列指针头的地址
 int H[N];//行指针头
 int S[N];//记录列链表中节点的总数
 int size,n,m,ak;
 int mark[N][N],visit[N];  
const double eps=1e-7;  

void prepare(int c)  
{  
        for(int i=0;i<=c;i++)  
          {  
            S[i]=0;U[i]=D[i]=i;  
            L[i+1]=i;R[i]=i+1;  
          }  
          R[c]=0;  
          size=c+1;  
          memset(H,-1,sizeof(H));  
} 

 void Link(int r,int c)
 {
     S[c]++;C[size]=c;
     U[size]=U[c];D[U[c]]=size;
     D[size]=c;U[c]=size;
     if(H[r]==-1) H[r]=L[size]=R[size]=size;
     else
     {
         L[size]=L[H[r]];R[L[H[r]]]=size;
         R[size]=H[r];L[H[r]]=size;
     }
     size++;
 }
 void remove(int Size)
 {
     int j;
     for(j=D[Size];j!=Size;j=D[j])
         L[R[j]]=L[j],R[L[j]]=R[j];
 }
 void resume(int Size)
 {
     int j;
     for(j=D[Size];j!=Size;j=D[j])
         L[R[j]]=R[L[j]]=j;
 }
 int h()
 {
     int count=0,i,j,k;
     memset(visit,0,sizeof(visit));
     for(i=R[0];i;i=R[i])
     {
         if(visit[i]) continue;
         count++;
         for(j=D[i];j!=i;j=D[j])
         {
             for(k=R[j];k!=j;k=R[k])
                 visit[C[k]]=1;
         }
     }
     return count;
 }
 void Dance(int k)
 {
     int i,j,min,c;
     if(k+h()>=ak) return;
     if(!R[0])
     {
         if(k<ak) ak=k;
         return;
     }
     for(min=N,i=R[0];i;i=R[i])
         if(min>S[i]) min=S[i],c=i;
     for(i=D[c];i!=c;i=D[i])
     {
         remove(i);
         for(j=R[i];j!=i;j=R[j])
             remove(j);
         Dance(k+1);
         for(j=R[i];j!=i;j=R[j])
             resume(j);
         resume(i);
     }
 }
struct point  
{  
    double x,y;  
}rar[55],city[55];  
double dis(point a,point b)  
{  
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));  
}  
int main()  
{  
     int ca,k,K;  
     scanf("%d",&ca);  
     while(ca--)  
     {  
      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",&rar[i].x,&rar[i].y);  
       
  
      double L=0,R=10000,mid;  
       
      while(R-L>eps)  
      {   
        prepare(n);  
        mid=(R+L)/2.0;  
        for(int i=1;i<=m;i++)  
        {  
            for(int j=1;j<=n;j++)  
            {  
                if(dis(rar[i],city[j])<mid+eps)  
                Link(i,j);  
            }  
        }  
        ak=N+1;  
        Dance(0);  
        //printf("%d###\n",ak);  
        if(ak>K)  
        {  
            L=mid;  
        }  
        else   
        {  
            R=mid;  
        }  
      }  
      printf("%.6lf\n",R);  
      }  
 return 0;  
}  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值