您的位置:首页 > 其它

hdu 2295 Radar DLX 重复覆盖问题

2012-10-29 23:20 274 查看
http://acm.hdu.edu.cn/showproblem.php?pid=229

题意:

一个国家有n个城市,m个雷达,我们同时操作的雷达数最多为k,给出城市与国家的坐标,求小于等于k的操作下,雷达覆盖的能够覆盖所有城市的最小覆盖半径。

思路:

城市作为列,雷达作为行,二分枚举雷达的半径+DLX重复覆盖求解。

View Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>

using namespace std;
//  freopen("data.in","r",stdin);
#define CL(a,num) memset((a),(num),sizeof(a))
#define inf 0x7f7f7f7f
#define M 55
#define N 55
#define maxn 3317

const double eps = 1e-8;
const int head = 0;

struct node{
double x,y;
}city
,rar[M];

int u[maxn],d[maxn],l[maxn],r[maxn],c[maxn],row[maxn];

int s
;
bool hash[M];
int n,m,k;
int size;

int dblcmp(double x){
if (x > eps) return 1;
else if (x < -eps) return -1;
else return 0;
}
bool isok(int a,int b,double R){
double x = rar[a].x - city[b].x;
double y = rar[a].y - city[b].y;
double s = x*x + y*y;
if (dblcmp(R - s) >= 0) return true;
else return false;
}
void init(){
int i;
for (i = 1; i <= n; ++i){
l[i] = i - 1;  r[i] = i + 1;
u[i] = d[i] = i;
c[i] = i;  s[i] = 0;
}
l[head] = n; r[head] = 1;
r
= head;
size = n + 1;
}
void build(int R){
int i,j;
for (i = 1; i <= m; ++i){//枚举行
int rh = -1;
for (j = 1; j <= n; ++j){//枚举列
if (isok(i,j,R)){//满足条件即可以覆盖
int x = j;
c[size] = x;
row[size] = i;
s[x]++;

u[size] = u[x];
d[u[x]] = size;
u[x] = size;
d[size] = x;
if (rh == -1){
l[size] = r[size] = size;
rh = size;
}
else{
l[size] = l[rh];
r[l[rh]] = size;
l[rh] = size;
r[size] = rh;
}
size++;
}
}
}
}
void remove(int ci){
int i;
for (i = d[ci]; i != ci; i = d[i]){
l[r[i]] = l[i];
r[l[i]] = r[i];
}
}
void resume(int ci){
int i;
for (i = u[ci]; i != ci; i = u[i]){
l[r[i]] = r[l[i]] = i;
}
}
int h(){
int i,j;
int res = 0;
CL(hash,false);
for (i = r[head]; i != head; i = r[i]){
if (!hash[i]){
res++;
hash[i] = true;
for (j = d[i]; j != i; j = d[j]){
for (int k = r[j]; k != j; k = r[k]){
hash[c[k]] = true;
}
}
}
}
return res;
}
bool dfs(int dep){
int i,j;
if (dep + h() > k) return false;
if (r[head] == head) return true;

int MIN = inf, ci = 0;
for (i = r[head]; i != head; i = r[i]){
if (s[i] < MIN){
MIN = s[i];
ci = i;
}
}
for (i = d[ci]; i != ci; i = d[i]){
remove(i);
for (j = r[i]; j != i; j = r[j]){
remove(j);
}
if (dfs(dep + 1)) return true;
for (j = l[i]; j != i; j = l[j]){
resume(j);
}
resume(i);
}
return false;
}
int main(){
// freopen("din.txt","r",stdin);
int i,j;
int T;
scanf("%d",&T);
while (T--){
scanf("%d%d%d",&n,&m,&k);

for (i = 1; i <= n; ++i) scanf("%lf%lf",&city[i].x,&city[i].y);
for (j = 1; j <= m; ++j) scanf("%lf%lf",&rar[j].x,&rar[j].y);

double L = 0, R = 50000.0;
double ans = 0;
while (dblcmp(R - L) > 0){
double mid = (R + L)/2.0;
init();
build(mid*mid);//这里不知道为啥这么坑爹,我开方求不对。
if (dfs(0)){
ans = mid;
R = mid;
}
else L = mid;
}
printf("%.6lf\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: