HDU 2295 Radar(二分+DLX重复覆盖)

来源:互联网 发布:单片机电子时钟设计 编辑:程序博客网 时间:2024/05/16 15:05

题目地址
题意:有n个城市,m个可以装雷达的地方,你的资金最多只能装k台雷达,问在这个限制条件下雷达的最小覆盖半径为多少。
思路:二分枚举半径长度,然后通过这个限制条件去建立矩阵(行为该雷达能覆盖的地方,列为该地方能被多少个雷达覆盖),当这个m*n的矩阵建好以后跑一边DLX重复覆盖就好了,当需要删除的行数大于k时就增大半径长度,反之减小。

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 1010#define MAXSIZE 1010*1010#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;const double eps = 1e-8;struct node {    int left, right, up, down, col, row;}mapp[MAXSIZE];int S[N], H[N];//S记录该列中1元素的个数int head, cnt;int len;int n, m, K;struct nope {    double x, y;}A[N], B[N];struct Dancing_Links_X {    void init() {        head = 0;        for (int i = 0; i <= n; i++) {            S[i] = 0;            mapp[i].up = mapp[i].down = i;            mapp[i].left = (i == 0 ? n : i - 1);            mapp[i].right = (i == n ? 0 : i + 1);        }        cnt = n;        memset(H, -1, sizeof(H));    }    void link(int x, int y) {        cnt++;        mapp[cnt].row = x;        mapp[cnt].col = y;        S[y]++;        mapp[cnt].up = mapp[y].up;        mapp[cnt].down = y;        mapp[mapp[y].up].down = cnt;        mapp[y].up = cnt;        if (H[x] == -1) H[x] = mapp[cnt].left = mapp[cnt].right = cnt;        else {            mapp[cnt].left = mapp[H[x]].left;            mapp[cnt].right = H[x];            mapp[mapp[H[x]].left].right = cnt;            mapp[H[x]].left = cnt;        }    }    void remove(int c) {//删去c这个点,以及关联的一列        for (int i = mapp[c].down; i != c; i = mapp[i].down) {            mapp[mapp[i].left].right = mapp[i].right;            mapp[mapp[i].right].left = mapp[i].left;        }    }    void resume(int c) {//恢复c这个点,以及关联的一列        for (int i = mapp[c].up; i != c; i = mapp[i].up) {            mapp[mapp[i].left].right = i;            mapp[mapp[i].right].left = i;        }    }    bool used[N];    int h() {        int sum = 0;        for (int i = mapp[head].right; i != head; i = mapp[i].right) used[i] = false;        for (int i = mapp[head].right; i != head; i = mapp[i].right) {            if (!used[i]) {                sum++;                used[i] = true;                for (int j = mapp[i].down; j != i; j = mapp[j].down)                    for (int k = mapp[j].right; k != j; k = mapp[k].right)                         used[mapp[k].col] = true;            }        }        return sum;    }    void dance(int nums) {        if (nums + h() >= len) return;        if (mapp[head].right == head) {            len = min(len, nums);            return;        }        int s = inf, c;        for (int t = mapp[head].right; t != head; t = mapp[t].right) {            if (S[t] < s) s = S[t], c = t;        }        for (int i = mapp[c].down; i != c; i = mapp[i].down) {            remove(i);            for (int j = mapp[i].right; j != i; j = mapp[j].right) {                remove(j);            }            dance(nums + 1);            for (int j = mapp[i].left; j != i; j = mapp[j].left) {                resume(j);            }            resume(i);        }        return;    }}DLX;double dis(int a, int b) {    return sqrt((A[a].x - B[b].x)*(A[a].x - B[b].x) + (A[a].y - B[b].y)*(A[a].y - B[b].y));}bool solve(double R) {    DLX.init();    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {            if (dis(i, j)<=R) {                DLX.link(j, i);            }        }    }    len = K + 1;    DLX.dance(0);    if (len > K) {        return false;    }    return true;}int main() {    int T;    scanf("%d", &T);    while (T--) {        scanf("%d%d%d", &n, &m, &K);        for (int i = 1; i <= n; i++) scanf("%lf%lf", &A[i].x, &A[i].y);        for (int i = 1; i <= m; i++) scanf("%lf%lf", &B[i].x, &B[i].y);        double l, r, mid;        l = 0; r = 10000;        while (r - l>eps) {            mid = (l + r) / 2;            if (solve(mid)) r = mid;            else l = mid;        }        printf("%.6lf\n", r);    }    return 0;}
原创粉丝点击