hdu 2295 Radar DLX 重复覆盖问题

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[N],rar[M];

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

int s[N];
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[n] = 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;
}

 

转载于:https://www.cnblogs.com/E-star/archive/2012/10/29/2745599.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值