您的位置:首页 > 其它

hdu 2295 dlx重复覆盖+二分答案

2015-05-16 23:10 399 查看
题目大意:

有一堆雷达工作站,安放至多k个人在这些工作站中,找到一个最小的雷达监控半径可以使k个工作人所在的雷达工作站覆盖所有城市

二分半径的答案,每次利用dlx的重复覆盖来判断这个答案是否正确

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <climits>
#include <cmath>

using namespace std;
#define N 55
#define MAXNODE 3000
const double INF = 1e9;
const double eps = 1e-8;

int n,m,k;

struct DLX{
int n,m,size;
int U[MAXNODE] , D[MAXNODE] , L[MAXNODE] , R[MAXNODE];
int col[MAXNODE] , row[MAXNODE];
int first
, cnt_col
;
bool v[MAXNODE];

void init(int _n , int _m)
{
n = _n , m = _m , size = _m;
for(int i=0 ; i<=m ; i++){
U[i] = D[i] = i;
L[i] = i-1 , R[i] = i+1;
col[i] = i , row[i] = 0;
}
L[0] = m , R[m] = 0;
for(int i=1 ; i<=n ; i++) first[i] = -1;
for(int i=1 ; i<=m ; i++) cnt_col[i] = 0;
}

void link(int r , int c)
{
++size;
U[D[c]] = size , D[size] = D[c];
U[size] = c , D[c] = size;
cnt_col[c]++;

if(first[r]<0) first[r] = L[size] = R[size] = size;
else{
R[size] = R[first[r]] , L[R[first[r]]] = size;
L[size] = first[r] , R[first[r]] = size;
}
row[size] = r , col[size] = c;
}

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;
}
}

int f()
{
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)
{
//这里k表示题目所给意思让我们至多在dlx中选择k行
if(d+f() > k) return false;
if(!R[0]) return d<=k;
int st = R[0];
for(int i=R[0] ; i!=0 ; i=R[i])
if(cnt_col[st]>cnt_col[i]) st=i;

for(int i=D[st] ; i!=st ; 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;
}
}dlx;

struct Point{
double x,y;
}p1
, p2
;

double getDis(int i , int j)
{
return sqrt((p1[i].x-p2[j].x)*(p1[i].x-p2[j].x)+(p1[i].y-p2[j].y)*(p1[i].y-p2[j].y));
}

bool check(double mid)
{
dlx.init(m , n);
for(int i=1 ; i<=m ; i++){
for(int j=1; j<=n ;j++){
if(getDis(j , i)<=mid) dlx.link(i,j);
}
}
return dlx.Dance(0);
}

double bin_search()
{
double l=0 , r=INF;
while(r-l>eps){
double mid = (l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
return r;
}

int main()
{
// freopen("a.in" , "r" , stdin);
int T;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d%d" , &n , &m , &k);
for(int i=1 ; i<=n ; i++)
scanf("%lf%lf" , &p1[i].x , &p1[i].y);
for(int i=1 ; i<=m ; i++)
scanf("%lf%lf" , &p2[i].x , &p2[i].y);
printf("%.6lf\n" , bin_search());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: