您的位置:首页 > 其它

HDU_2295_Radar(DancingLinksX重复覆盖+二分)

2016-04-30 23:55 441 查看


Radar

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3333 Accepted Submission(s): 1285



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

1
3 3 2
3 4
3 1
5 4
1 1
2 2
3 3


Sample Output

2.236068


Source

The 4th Baidu Cup final

Recommend

lcy

DancingLinksX重复覆盖+二分

题意

给出一堆城市和雷达的坐标

雷达有一个覆盖范围

求所有城市被雷达覆盖时,雷达的最小覆盖半径

做法

二分一个雷达的半径

雷达作为行,城市作为列

雷达覆盖范围内的城市对应一个1

然后DancingLinksX重复覆盖即可

特别注意DancingLinksX重复覆盖的模板经过了A*优化

如果没有优化会TLE而且貌似所有的重复覆盖都用了这个优化

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;

const int MN=55;
const int MM=55;
const int MNN=MN*MM+MM; //最大点数

int n,m,k;//n城市m雷达

struct DLX
{
int n,m,si;//n行数m列数si目前有的节点数
//十字链表组成部分
int U[MNN],D[MNN],L[MNN],R[MNN],Row[MNN],Col[MNN];
//第i个结点的U向上指针D下L左R右,所在位置Row行Col列
int H[MN],S[MM]; //记录行的选择情况和列的覆盖情况
int ansd,ans[MN];
int mk;  //最大的可选行数
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-1;
R[i]=i+1;         //横向的连起来
}
R[m]=0;L[0]=m;
si=m;                 //目前用了前0~m个结点
for(int i=1;i<=n;i++)
H[i]=-1;
}
void link(int r,int c)    //插入点(r,c)
{
++S[Col[++si]=c];     //si++;Col[si]=c;S[c]++;
Row[si]=r;
D[si]=D[c];
U[D[c]]=si;
U[si]=c;
D[c]=si;
if(H[r]<0)
H[r]=L[si]=R[si]=si;
else
{
R[si]=R[H[r]];
L[R[H[r]]]=si;
L[si]=H[r];
R[H[r]]=si;
}
}
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[MNN];
int h() //估值
{
int ret=0;
for(int c=R[0];c!=0;c=R[c])
v[c]=1;
for(int c=R[0];c!=0;c=R[c])
if(v[c])
{
ret++;
v[c]=0;
for(int i=D[c];i!=c;i=D[i])
for(int j=R[i];j!=i;j=R[j])
v[Col[j]]=0;
}
return ret;

}
bool dance(int d)
{
if(d+h()>mk)  //利用A*优化
return 0;
if(R[0]==0)
return d<=mk;
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 1;
for(int j=L[i];j!=i;j=L[j])
resume(j);
resume(i);
}
return 0;
}
}dlx;

struct Node
{
int x,y;
}radar[MN],city[MM];
double dis[MM][MN];

const double eps=1e-8;
bool work(double mi)
{
dlx.init(m,n);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
if(dis[i][j]<mi+eps)
dlx.link(i,j);
return dlx.dance(0);

}
double bs()
{
double lo=0,hi=1500.0;
double mid,ans=1000000;
while(hi-lo>eps)
{
mid=(lo+hi)/2.0;
if(work(mid))
{
ans=min(ans,mid);
hi=mid;
}
else
lo=mid;
}
return ans;
}

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
dlx.mk=k;
for(int i=1;i<=n;i++)
scanf("%d%d",&city[i].x,&city[i].y);
for(int i=1;i<=m;i++)
scanf("%d%d",&radar[i].x,&radar[i].y);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dis[j][i]=sqrt(1.0*(city[i].x-radar[j].x)*(city[i].x-radar[j].x)
+(city[i].y-radar[j].y)*(city[i].y-radar[j].y));
printf("%.6lf\n",bs());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: