ZOJ 3209 Treasure Map (Dancing Links)

来源:互联网 发布:ug零件产品编程教程 编辑:程序博客网 时间:2024/05/17 04:06

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3372

题目大意:给p个方块,问最少的方块数目精确覆盖n*m的矩形。若不存在则输出-1。

题目思路:这是一个DLX精确覆盖的模板题。

把每个格子当成一个列,要覆盖所有格子。

取x行,使得每一列都存在一个1 —-> 从p中取x个格子。

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;const int maxnode = 500010;const int MaxM = 1010;const int MaxN = 510;struct 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;    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 d)    {        //剪枝下        if(ansd != -1 && ansd <= d)return;        if(R[0] == 0)        {            if(ansd == -1)ansd = d;            else if(d < ansd)ansd = d;            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])        {            for(int j = R[i];j != i;j = R[j])remove(Col[j]);            Dance(d+1);            for(int j = L[i];j != i;j = L[j])resume(Col[j]);        }        resume(c);    }};DLX g;int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int T;    int n,m,p;    scanf("%d",&T);    while(T--)    {        scanf("%d%d%d",&n,&m,&p);        g.init(p,n*m);        int x1,y1,x2,y2;        for(int k = 1;k <= p;k++)        {            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);            for(int i = x1+1;i <= x2;i++)                for(int j = y1+1;j <= y2;j++)                    g.Link(k,j + (i-1)*m);        }        g.ansd = -1;        g.Dance(0);        printf("%d\n",g.ansd);    }    return 0;}



原创粉丝点击