hdu 2295 dancing links 求重复覆盖

来源:互联网 发布:龙卷风网络歌手 编辑:程序博客网 时间:2024/06/06 02:04

Radar

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2639    Accepted Submission(s): 1025


Problem Description
N cities of the Java Kingdom need to be covered by radars for being in a state of war. Since the kingdom has M radar stations but only K operators, we can at most operate K radars. All radars have the same circular coverage with a radius of R. Our goal is to minimize R while covering the entire city with no more than K radars.
 

Input
The input consists of several test cases. The first line of the input consists of an integer T, indicating the number of test cases. The first line of each test case consists of 3 integers: N, M, K, representing the number of cities, the number of radar stations and the number of operators. Each of the following N lines consists of the coordinate of a city.
Each of the last M lines consists of the coordinate of a radar station.

All coordinates are separated by one space.
Technical Specification

1. 1 ≤ T ≤ 20
2. 1 ≤ N, M ≤ 50
3. 1 ≤ K ≤ M
4. 0 ≤ X, Y ≤ 1000
 

Output
For each test case, output the radius on a single line, rounded to six fractional digits.
 

Sample Input
13 3 23 43 15 41 12 23 3
 

Sample Output
2.236068
 

Source
The 4th Baidu Cup final
/*第一次正式写Dancing Links解重复覆盖的问题,感觉和精确覆盖相比,精确覆盖要求每列只能有一个1,因此在删除一列的时候要连带删除这一列中为1的所有行,同时要将选出的行中为1的列全部删除,而重复覆盖问题每列可以有多个1,但一旦选择了某一行,这一行上所有为1的列就可以纳入不考虑的范围了,因此删除操作就变成了删除某一行并删除这一行中为1的所有列。注意减枝,由于矩阵密度下降会变慢(因为去掉的少了),因此要加上一个强剪枝。这个剪枝利用的思想是A*搜索中的估价函数。即,对于当前的递归深度K下的矩阵,估计其最好情况下(即最少还需要多少步)才能出解。也就是,如果将能够覆盖当前列的所有行全部选中,去掉这些行能够覆盖到的列,将这个操作作为一层深度。重复此操作直到所有列全部出解的深度是多少。如果当前深度加上这个估价函数返回值,其和已然不能更优(也就是已经超过当前最优解),则直接返回,不必再搜。*/#include<stdio.h>#include<string.h>#include<math.h>#define M 2500#define eps 1e-8//精度大于等于7都可以过#define N 100int s[M],row[M],col[M],u[M],d[M],r[M],l[M],h[M],size,vis[M];struct node{  double x,y;}a[N],b[N];double dis(int i,int j){  return sqrt((a[i].x-b[j].x)*(a[i].x-b[j].x)+(a[i].y-b[j].y)*(a[i].y-b[j].y));}void init(int n,int m){  int i;   for(i=0;i<=m;i++)   {      s[i]=0;      d[i]=u[i]=i;      l[i]=i-1;      r[i]=i+1;   }   l[0]=m; r[m]=0;   size=m;   for(i=1;i<=n;i++)     h[i]=-1;}void link(int x,int y){     ++s[col[++size]=y];     row[size]=x;     u[d[y]]=size;     d[size]=d[y];     d[y]=size;     u[size]=y;     if(h[x]<0)      h[x]=l[size]=r[size]=size;     else     {        l[r[h[x]]]=size;        r[size]=r[h[x]];        r[h[x]]=size;        l[size]=h[x];     }}void remove(int c){   int i;   for(i=d[c];i!=c;i=d[i])   {     l[r[i]]=l[i];     r[l[i]]=r[i];   }}void resume(int c){     int i;    for(i=u[c];i!=c;i=u[i])    {       l[r[i]]=i;       r[l[i]]=i;    }}int f(){   int i,j,k,num=0;   memset(vis,0,sizeof(vis));   for(i=r[0];i!=0;i=r[i])   {      if(!vis[i])      {         num++;         for(j=d[i];j!=i;j=d[j])            for(k=r[j];k!=j;k=r[k])              vis[col[k]]=1;      }   }   return num;}int dance(int x,int k){   int c,i,j;    if(x+f()>k)//减枝      return 0;    if(r[0]==0)      return x>k?0:1;    c=r[0];    for(i=r[0];i!=0;i=r[i])      if(s[i]<s[c])        c=i;    for(i=d[c];i!=c;i=d[i])    {        remove(i);       for(j=r[i];j!=i;j=r[j])         remove(j);       if(dance(x+1,k)) return 1;       for(j=l[i];j!=i;j=l[j])         resume(j);      resume(i);    }    return 0;}int main(){  int t,i,j,n,m,k;  double ans,l,r,mid;  //freopen("a.txt","r",stdin);  scanf("%d",&t);  while(t--)  {    scanf("%d%d%d",&n,&m,&k);    for(i=1;i<=n;i++)      scanf("%lf%lf",&a[i].x,&a[i].y);    for(i=1;i<=m;i++)      scanf("%lf%lf",&b[i].x,&b[i].y);      l=0;r=1500;      while(l-r<=eps)      {        mid=(l+r)/2.0;        init(m,n);        for(i=1;i<=n;i++)          for(j=1;j<=m;j++)            if(dis(i,j)-mid<=eps)                 link(j,i);         //printf("answer=%d\n",dance(0,k));         if(dance(0,k))         {           ans=mid;           r=mid-eps;          }          else           l=mid+eps;      }      printf("%.6lf\n",ans);  }  return 0;}


0 0
原创粉丝点击