ZOJ Treasure Map DLX 精确覆盖

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3372

题意:

给你一个n*m的大矩形,然后给你p个小矩形,让你从中选出若干小矩形填满这个大矩形,这里保证所选的小矩形不存在相互覆盖。

思路:
才开始看到大牛的dlx分类里面看了之后,没什么想法,可能就做了一个题的原因把。说是把整个大矩形的面积看n*m的作列,每个小矩形看作行,然后拆出他所能覆盖的列然后问题就转化成了DLX问题了。

吐槽以下,这题我交了34遍啊。才开始自己想到了怎么写了就写了一下,中间出现各种错误, i : x1 到 x2 - 1 j: y1 + 1 到 y2 转化为本行所能覆盖的列时乘错了 i*tm + j才对,我给乘成tn了。还有就是初始化l,r,u,d,s,c时开始写的太搓了,后来又借鉴了一下写的不错的。 但是还是tle  个都无语了。。后来把恢复的顺序改为删除的顺序的相反顺序就A了。网上几乎都是按删除顺序的相反顺序恢复的,我个人觉得应该没问题啊,而且hust的那道模板题目也能过啊,不明白,希望有人指教。。谢谢了。。后来重新整理了一下模板。

View Code
#include <cstdio>

#include <cstring>

#include <iostream>





#define CL(a,num) memset((a),(num),sizeof(a))

#define inf 0x7f7f7f7f

#define M 907

#define N 450024



using namespace std;



const int head = 0;

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

int s[N];

int m;



int ans;

bool flag;



inline

void remove(int ci){

    int i,j;

    l[r[ci]] = l[ci];

    r[l[ci]] = r[ci];

    for (i = d[ci]; i != ci; i = d[i]){

        for (j = r[i]; j != i; j = r[j]){

            u[d[j]] = u[j];

            d[u[j]] = d[j];

            s[c[j]]--;

        }

    }

}

inline

void resume(int ci){

    int i,j;

    l[r[ci]] = r[l[ci]]  = ci;

    for (i = u[ci]; i != ci; i = u[i]){

         for (j = l[i]; j != i; j = l[j]){

             u[d[j]] = j;

             d[u[j]] = j;

             s[c[j]]++;

         }

     }

}

void dfs(int k){

    int i,j;

    if (k >= ans) return;

    if (r[head] == head){

        ans = min(ans,k);

        flag = true;

        return ;

    }

    int MIN = inf, ci = 0;

    for (i = r[head]; i != head; i = r[i]){

        if (s[i] < MIN){

            MIN = s[i];

            ci = i;

        }

    }



    remove(ci);

    for (i = d[ci]; i != ci; i = d[i]){

        for (j = r[i]; j != i; j = r[j]){

            remove(c[j]);

        }

        dfs(k + 1);

        for (j = l[i]; j != i; j = l[j]){

            resume(c[j]);

        }

    }

    resume(ci);

}

inline

void init(int m){

    int i;

    for (i = 1; i <= m; ++i){

        l[i] = i - 1;

        r[i] = i + 1;

        u[i] = d[i] = i;

        c[i] = i;

        s[i] = 0;

    }

    l[head] = m; r[head] = 1;

    r[m] = head;

}

int Get(){

    int num = 0;

    char ch = getchar();

    while (ch < '0' || ch > '9') ch = getchar();

    while (ch >= '0' && ch <= '9'){

        num = num*10 + ch - '0';

        ch = getchar();

    }

    return num;

}

int main(){

   //freopen("data.in","r",stdin);

    int i,j;

    int tn,tm,p;

    int T;

    scanf("%d",&T);

    while (T--){

        //scanf("%d%d%d",&tn,&tm,&p);

        tn = Get(); tm = Get(); p = Get();

        int m = tn*tm;

        init(m);

        int size = m + 1;

        int x1,y1,x2,y2;

        for (int b = 0; b < p; ++b){

            //scanf("%d%d%d%d",&x1,&y1,&x2,&y2);

            x1 = Get(); y1 = Get();

            x2 = Get(); y2 = Get();

            int rh = -1;

            x2--; y1++;

            for (i = x1; i <= x2; ++i){

                for (j = y1; j <= y2; ++j){

                    int x = i*tm + j;

                    row[size] = b + 1;

                    c[size] = x;

                    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++;

                }

            }

        }

        ans = inf;

        flag = false;

        for (i = 1; i <= m; ++i){

            if (s[i] == 0){

                flag = true;

                break;

            }

        }

        if (flag){

            printf("-1\n");

            continue;

        }

        dfs(0);

        if (flag) printf("%d\n",ans);

        else printf("-1\n");

    }

    return 0;

}

 

你可能感兴趣的:(map)