ZOJ 3209 Treasure Map (DLX精确覆盖问题)

来源:互联网 发布:路由器mac地址有什么用 编辑:程序博客网 时间:2024/05/29 08:41

题目大意:

给出一个n*m的矩形, n, m <= 30, 从p <= 500个矩形中选择一些矩形使得这些矩形不重合但刚好拼凑出n*m的这个矩形(矩形位置都不能移动), 求从给出的矩形中最少需要挑出几个才能满足这个条件


大致思路:

就是将n*m个小的1*1的正方形视作一个单位做精确覆盖问题就好了

最坏情况下900列, 500行, 直接用DLX就可以


代码如下:

Result  :  Accepted     Memory  :  10828 KB     Time  :  70 ms

/* * Author: Gatevin * Created Time:  2015/10/4 18:10:46 * File Name: Sakura_Chiyo.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;#define maxnode 450010#define maxn 510#define maxm 1000struct DLX{    int n, m, size;    int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode];    int H[maxn], S[maxm];    int ansd, ans[maxn];    void init(int _n, int _m)    {        n = _n;        m = _m;        for(int i = 0; i <= m; i++)        {            S[i] = 0;            U[i] = D[i] = i;            L[i] = i - 1;            R[i] = i + 1;        }        R[m] = 0; L[0] = m;        size = m;        for(int i = 1; i <= n; i++) H[i] = -1;    }    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(int i = D[c]; i != c; i = D[i])            for(int j = R[i]; j != i; j = R[j])            {                U[D[j]] = U[j];                D[U[j]] = D[j];                --S[Col[j]];            }    }    void resume(int c)    {        for(int i = U[c]; i != c; i = U[i])            for(int j = L[i]; j != i; j = L[j])                ++S[Col[U[D[j]] = D[U[j]] = j]];        L[R[c]] = R[L[c]] = c;    }    void Dance(int dep)    {        if(dep >= ansd) return;        if(R[0] == 0)        {            ansd = min(ansd, dep);            return;        }        int c = R[0];        for(int i = R[0]; i != 0; i = R[i])            if(S[i] < S[c])                c = i;        remove(c);        for(int i = D[c]; i != c; i = D[i])        {            ans[dep] = Row[i];            for(int j = R[i]; j != i; j = R[j]) remove(Col[j]);            Dance(dep + 1);            for(int j = L[i]; j != i; j = L[j]) resume(Col[j]);        }        resume(c);        return;    }    void solve()    {        int N, M, p;        scanf("%d %d %d", &N, &M, &p);        init(p, N*M);        for(int i = 1; i <= p; i++)        {            int x1, y1, x2, y2;            scanf("%d %d %d %d", &x1, &y1, &x2, &y2);            for(int x = x1; x < x2; x++)                for(int y = y1; y < y2; y++)                    Link(i, x*M + y + 1);        }        ansd = p + 1;        Dance(0);        if(ansd == p + 1)            puts("-1");        else printf("%d\n", ansd);        return;    }};DLX dlx;int main(){    int T;    scanf("%d", &T);    while(T--)        dlx.solve();    return 0;}


0 0
原创粉丝点击