zoj3209 Treasure Map DLX

     一片区域从0 0到 n,m,现有若干个矩形碎片,问最少需要多少个碎片可以不重复的覆盖这片区域。

      第一道要自己建模型的题..把格点编号,看做矩阵的列,把每个碎片的编号看成行,这样可以转化成01矩阵中选若干行使得每一列恰有一个1的问题,建好表之后跑一遍DLX就行。因为这题是一行一行的添加的,所以可以省去每行的表头,这么小效率可能会高一点...

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n,m,anss,k,num;
 int nn,mm;
const int inf=(1<<29);
const int maxx=610;
const int maxy=1010;
const int maxn=610*1010;
int col[maxn],row[maxn],ans[maxn];
    int S[maxy];
    int size;
    int U[maxn],D[maxn],L[maxn],R[maxn];
struct DLX
{
    int tail,head;
    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)
    {
        L[R[c]]=c;
        R[L[c]]=c;
        for (int i=U[c]; i!=c; i=U[i])
        {
            for (int j=L[i]; j!=i; j=L[j])
            {
                U[D[j]]=j;
                D[U[j]]=j;
                ++S[col[j]];
            }
        }
    }
    bool dfs(int k)
    {
        if (k>=anss) return false;

        int c=R[0];
        if (c==0)
        {
            anss=k;
            return true;
        }
        for (int i=R[0]; i!=0; i=R[i])
        {
            if (S[c]>S[i]) c=i;
        }
        remove(c);
        for (int i=D[c]; i!=c; i=D[i])
        {
            ans[k]=row[i];
            for (int j=R[i]; j!=i; j=R[j]) remove(col[j]);
            dfs(k+1);
            for (int j=L[i]; j!=i; j=L[j]) resume(col[j]);
        }
        resume(c);
        return false;
    }
    void init(int m)
    {
        int x1,x2,y1,y2;

        for (int i=0; i<=m; i++)
        {
            S[i]=0;
            L[i]=i-1;
            R[i]=i+1;
            U[i]=D[i]=i;
        }
        L[0]=m;
        R[m]=0;
        size=m+1;

        for (int i=1; i<=k; i++)
        {
            head=tail=size;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            for (int x=x1; x<x2; x++)
             for (int y=y1; y<y2; y++)
             {

                int pos=y*nn+x+1;

                ++S[col[size]=pos];
                U[D[pos]]=size;
                D[size]=D[pos];
                U[size]=pos;
                D[pos]=size;

                R[size]=tail; L[tail]=size;
                L[size]=head; R[head]=size;
                tail=size;
                size++;
             }
        }

    }
}dlx;

int main()
{
//    freopen("in.txt","r",stdin);
    int tt;
    scanf("%d",&tt);

    while(tt--)
    {
        anss=inf;
        scanf("%d%d%d",&nn,&mm,&k);
        n=k;
        m=(nn)*(mm);
//        int spc=0;
//        for (int i=0; i<nn; i++)
//         for (int j=0; j<mm; j++)
//         g[i][j]=++spc;
        dlx.init(m);
        bool bad=false;
        for (int i=1; i<=m; i++)
        if (!S[i])
        {
            bad=true;
            break;
        }
        if (bad)
        {
            puts("-1");
            continue;
        }
        dlx.dfs(0);
        if (anss<inf)
        {
            printf("%d\n",anss);
        }
        else
        {
            puts("-1");
        }

    }
    return 0;
}


你可能感兴趣的:(zoj3209 Treasure Map DLX)