• zoj 3209.Treasure Map(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 = 510000;
    int n, m, k, t, len;
    
    struct DLX {
        int n, Size;//Size为尾指针,真正大小
        int row[MAX], col[MAX];//记录每个点的行列
        int U[MAX], D[MAX], R[MAX], L[MAX]; //4个链表
        int S[MAX],H[MAX];//每列1的个数
        int ncnt, ans[MAX];
        void init (int n) {
            this->n = n;
            ncnt = MAX;
            //增加n+1个辅助链表,从0到n
            for (int i = 0; i <= n; i++)
                U[i] = D[i] = i, L[i] = i - 1, R[i] = i + 1,S[i]=0;
            R[n] = 0, L[0] = n; //头尾相接
            Size = n + 1;
            memset (H, -1, sizeof H);
        }
        //单点添加
        void Link (int r, int c)
        {
            ++S[col[++Size] = c];
            row[Size] = r;
            D[Size] = D[c];
            U[D[c]] = Size;
            U[Size] = c;
            D[c] = Size;
            if (H[r] < 0) H[r] = L[Size] = R[Size] = Size;
            else
            {
                R[Size] = R[H[r]];
                L[R[H[r]]] = Size;
                L[Size] = H[r];
                R[H[r]] = Size;
            }
        }
        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 >= ncnt) return 0;
            //if (d + ff() > k) return 0;//重复覆盖
            if (R[0] == 0) {
                ncnt = min (ncnt, d);
                return 1;
            }
            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;
                dfs (d + 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;
        }
    } Dance;
    int columns[31][31 * 31];
    int main() {
        scanf ("%d", &t);
        while (t--) {
            memset (columns, 0, sizeof columns);
            scanf ("%d %d %d", &n, &m, &k);
            len = n * m;
            Dance.init (len);
            int x,y,xx,yy;
            for (int p = 1; p <= k; p++) {
                scanf ("%d %d %d %d", &x, &y, &xx, &yy);
                for (int i = x+1; i <= xx; i++)
                    for (int j = y+1; j <= yy; j++)
                        Dance.Link (p, j + (i-1)*m);
            }
            Dance.dfs (0);
            printf ("%d
    ", Dance.ncnt == MAX ? -1 : Dance.ncnt);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Linux中find常见用法示例
    PHP写的异步高并发服务器,基于libevent
    Prototype原型模式
    抽象工厂模式
    工厂方法模式
    简单工厂模式
    记一次皮肤过敏
    Thread类线程结束会唤醒使用其对象做锁而睡眠的线程
    位运算符
    逻辑运算符
  • 原文地址:https://www.cnblogs.com/keam37/p/4000958.html
Copyright © 2020-2023  润新知