zoukankan      html  css  js  c++  java
  • HDU 2295.Radar (DLX重复覆盖)

    2分答案+DLX判断可行

    不使用的估计函数的可重复覆盖的搜索树将十分庞大

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    using namespace std;
    
    #define FOR(i,A,s)  for(int i = A[s]; i != s; i = A[i])
    #define exp 1e-8
    
    const int MAX = 111111, MAXR = 1111, MAXC = 1111;
    int n, m, k, t;
    
    struct DLX {
        int n, Size;//Size为尾指针,真正大小
        int row[MAX], col[MAX];//记录每个点的行列
        int U[MAX], D[MAX], R[MAX], L[MAX]; //4个链表
        int S[MAXC];//每列1的个数
        int ncnt, ans[MAXR];
        void init (int n) {
            this->n = n;
            //增加n+1个辅助链表,从0到n
            for (int i = 0; i <= n; i++)
                U[i] = D[i] = i, L[i] = i - 1, R[i] = i + 1;
            R[n] = 0, L[0] = n; //头尾相接
            Size = n + 1;
            memset (S, 0, sizeof S);
        }
        //逐行添加
        void addRow (int r, int columns[111]) {
            int first = Size;
            for (int i = 1; i <= n ; i++) {
                if (columns[i] == 0) continue;
                int c = i;
                L[Size] = Size - 1, R[Size] = Size + 1;
                U[Size] = U[c], D[Size] = c;//插入第c列
                D[U[c]] = Size, U[c] = Size; //注意顺序!!!
                row[Size] = r, col[Size] = c;
                Size++, S[c]++;
            }
            if (Size > first)
                R[Size - 1] = first, L[first] = Size - 1; //头尾相接
        }
        void Remove (int c) {
            //精确覆盖
    //        L[R[c]] = L[c], R[L[c]] = R[c];
    //        FOR (i, D, c)
    //                     FOR (j, R, i)
    //                            U[D[j]] = U[j], D[U[j]] = D[j], --S[col[j]];
            //重复覆盖
            for (int i = D[c]; i != c; i = D[i])
                L[R[i]] = L[i], R[L[i]] = R[i];
        }
        void Restore (int c) {
    //        FOR (i, U, c)
    //                     FOR (j, L, i)
    //                            ++S[col[j]], U[D[j]] = j, D[U[j]] = j;
    //        L[R[c]] = c, R[L[c]] = c;
            //重复覆盖
            for (int i = U[c]; i != c; i = U[i])
                L[R[i]] = R[L[i]] = i;
        }
        bool v[MAX];
        int ff()
        {
            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 dfs (int d) {
            if (d + ff() > k) return 0;
            if (R[0] == 0) {
                ncnt = d;
                return d <= k;
            }
            int c = R[0];
            for (int i = R[0]; i != 0; i = R[i])
                if (S[i] < S[c])
                    c = i;
            //Remove (c);//精确覆盖
            FOR (i, D, c) {
                Remove (i);//重复覆盖
                ans[d] = row[i];
                //FOR (j, R, i) Remove (col[j]);
                FOR (j, R, i) Remove (j);
                if (dfs (d + 1) ) return 1;
                //FOR (j, L, i) Restore (col[j]);
                FOR (j, L, i) Restore (j);
                Restore (i);//重复覆盖
            }
            //Restore (c);//精确覆盖
            return 0;
        }
        bool solve (vector<int> &v) {
            v.clear();
            if (!dfs (0) ) return 0;
            for (int i = 0; i < ncnt; i++) v.push_back (ans[i]);
            return 1;
        }
    } f;
    struct node {
        int x, y;
    } g[100], Ra[100];
    int columns[111][111];
    double dis[111][111];
    inline double getdis (node a, node b) {
        return sqrt (double ( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) ) );
    }
    bool make (double mid) {
        f.init (n);
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                columns[i][j] = dis[i][j] <= mid;
        for (int i = 1; i <= m; i++)
            f.addRow (i, columns[i]);
        return f.dfs (0);
    }
    int main() {
        scanf ("%d", &t);
        while (t--) {
            scanf ("%d %d %d", &n, &m, &k);
            for (int i = 1; i <= n; i++)
                scanf ("%d %d", &g[i].x, &g[i].y);
            for (int i = 1; i <= m; i++)
                scanf ("%d %d", &Ra[i].x, &Ra[i].y);
            double l = 1e9, r = 0;
            for (int i = 1; i <= m; i++)
                for (int j = 1; j <= n; j++) {
                    dis[i][j]  = getdis (Ra[i], g[j]);
                    l = min (dis[i][j], l), r = max (r, dis[i][j]);
                }
            double ans = -1;
            while (r - l > 1e-7) {
                double mid = (r + l) / 2.;
                if (make (mid) ) {
                    ans = mid;
                    r = mid - exp;
                }
                else
                    l = mid + exp;
            }
            printf ("%.6f
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    如何导出和导入mysql数据(数据迁移)
    C# exe dll防止反编译-- dotNET_Reactor
    C#防止反编译
    WCF异常相关
    了解WCF的前世今生之实现服务端(一)
    svn忽略文件后缀
    马云给年轻人的10句忠告 真的后悔才看到!
    如何利用好清晨与夜间的时间?
    浙江旅游好去处
    突然觉得生活好累......
  • 原文地址:https://www.cnblogs.com/keam37/p/4000881.html
Copyright © 2011-2022 走看看