BZOJ1501 [NOI2005]智慧珠游戏

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解

题目(传送门)

题解

DLX  +  矩阵构建  (两个传送门)

对于这一题,矩阵的构建和数独有比较大的不同,常量表也打了很长。

我们要精确覆盖的信息有两种:

1.  每种形状限用一次

2.  每个格子限填一次

然后对于每个位置的每种形状的每个形态,建立相应的行即可。

常量表贼长。

我这样打,虽然比较长,但是有助于找茬。

代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int z[12]={4,2,8,1,4,8,4,8,8,1,4,8};
const int p[12][8][4][4]={
    //A
    {
        {
            {1,1,0,0},
            {1,0,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},
            {1,1,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},
            {0,1,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,1,0,0},
            {1,1,0,0},
            {0,0,0,0},
            {0,0,0,0}
        }
    },
    //B
    {
        {
            {1,1,1,1},
            {0,0,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},
            {1,0,0,0},
            {1,0,0,0},
            {1,0,0,0}
        }
    },
    //C
    {
        {
            {1,0,0,0},//1
            {1,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,1,0},//2
            {1,0,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,0,1,0},//3
            {1,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,1,0},//4
            {0,0,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},//5
            {1,0,0,0},
            {1,1,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//6
            {1,0,0,0},
            {1,0,0,0},
            {0,0,0,0}
        },
        {
            {0,1,0,0},//7
            {0,1,0,0},
            {1,1,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//8
            {0,1,0,0},
            {0,1,0,0},
            {0,0,0,0}
        }
    },
    //D
    {
        {
            {1,1,0,0},//1
            {1,1,0,0},
            {0,0,0,0},
            {0,0,0,0}
        }
    },
    //E
    {
        {
            {1,1,1,0},//1
            {1,0,0,0},
            {1,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},//2
            {1,0,0,0},
            {1,1,1,0},
            {0,0,0,0}
        },
        {
            {1,1,1,0},//3
            {0,0,1,0},
            {0,0,1,0},
            {0,0,0,0}
        },
        {
            {0,0,1,0},//4
            {0,0,1,0},
            {1,1,1,0},
            {0,0,0,0}
        }
    },
    //F
    {
        {
            {1,1,1,1},//1
            {0,1,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,1,1},//2
            {0,0,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,1,0,0},//3
            {1,1,1,1},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,0,1,0},//4
            {1,1,1,1},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},//5
            {1,1,0,0},
            {1,0,0,0},
            {1,0,0,0}
        },
        {
            {1,0,0,0},//6
            {1,0,0,0},
            {1,1,0,0},
            {1,0,0,0}
        },
        {
            {0,1,0,0},//7
            {1,1,0,0},
            {0,1,0,0},
            {0,1,0,0}
        },
        {
            {0,1,0,0},//8
            {0,1,0,0},
            {1,1,0,0},
            {0,1,0,0}
        }
    },
    //G
    {
        {
            {1,1,1,0},//1
            {1,0,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,1,0},//2
            {1,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//3
            {1,0,0,0},
            {1,1,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//4
            {0,1,0,0},
            {1,1,0,0},
            {0,0,0,0}
        }
    },
    //H
    {
        {
            {1,1,1,0},//1
            {1,1,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,1,0},//2
            {0,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//3
            {1,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,1,1,0},//4
            {1,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//5
            {1,1,0,0},
            {1,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},//6
            {1,1,0,0},
            {1,1,0,0},
            {0,0,0,0}
        },
        {
            {0,1,0,0},//7
            {1,1,0,0},
            {1,1,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//8
            {1,1,0,0},
            {0,1,0,0},
            {0,0,0,0}
        }
    },
    //I
    {
        {
            {1,1,1,0},//1
            {0,0,1,1},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,0,1,1},//2
            {1,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,1,1,1},//3
            {1,1,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//4
            {0,1,1,1},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},//5
            {1,0,0,0},
            {1,1,0,0},
            {0,1,0,0}
        },
        {
            {0,1,0,0},//6
            {1,1,0,0},
            {1,0,0,0},
            {1,0,0,0}
        },
        {
            {1,0,0,0},//7
            {1,1,0,0},
            {0,1,0,0},
            {0,1,0,0}
        },
        {
            {0,1,0,0},//8
            {0,1,0,0},
            {1,1,0,0},
            {1,0,0,0}
        }
    },
    //J
    {
        {
            {0,1,0,0},
            {1,1,1,0},
            {0,1,0,0},
            {0,0,0,0}
        }        
    },
    //K
    {
        {
            {1,0,0,0},//1
            {1,1,0,0},
            {0,1,1,0},
            {0,0,0,0}
        },
        {
            {1,1,0,0},//2
            {0,1,1,0},
            {0,0,1,0},
            {0,0,0,0}
        },
        {
            {0,1,1,0},//3
            {1,1,0,0},
            {1,0,0,0},
            {0,0,0,0}
        },
        {
            {0,0,1,0},//4
            {0,1,1,0},
            {1,1,0,0},
            {0,0,0,0}
        }
    },
    //L
    {
        {
            {1,1,1,1},//1
            {0,0,0,1},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,1,1,1},//2
            {1,0,0,0},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},//3
            {1,1,1,1},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {0,0,0,1},//4
            {1,1,1,1},
            {0,0,0,0},
            {0,0,0,0}
        },
        {
            {1,0,0,0},//5
            {1,0,0,0},
            {1,0,0,0},
            {1,1,0,0}
        },
        {
            {1,1,0,0},//6
            {1,0,0,0},
            {1,0,0,0},
            {1,0,0,0}
        },
        {
            {1,1,0,0},//7
            {0,1,0,0},
            {0,1,0,0},
            {0,1,0,0}
        },
        {
            {0,1,0,0},//8
            {0,1,0,0},
            {0,1,0,0},
            {1,1,0,0}
        }
    }
};
/**********************************************************/
const int N=4000,M=100,S=N*7+M;
//构建矩阵: 每个格子一个,每个形状一个 
struct DLX{
    int n,m,cnt;
    int x[S],y[S],L[S],R[S],U[S],D[S];
    int C[M],anscnt,ans[N];
    void init(int c){
        memset(x,0,sizeof x),memset(y,0,sizeof y);
        memset(L,0,sizeof L),memset(R,0,sizeof R);
        memset(U,0,sizeof U),memset(D,0,sizeof D);
        memset(C,0,sizeof C),memset(ans,0,sizeof ans);
        anscnt=0,m=c;
        for (int i=0;i<=m;i++)
            L[i]=i-1,R[i]=i+1,U[i]=D[i]=i;
        L[0]=m,R[m]=0,cnt=m;
    }
    void link(int i,int j){
        cnt++;
        x[cnt]=i;
        y[cnt]=j;
        L[cnt]=cnt-1;
        R[cnt]=cnt+1;
        D[cnt]=j;
        D[U[j]]=cnt;
        U[cnt]=U[j];
        U[j]=cnt;
        C[j]++;
    }
    void Delete(int k){
        L[R[k]]=L[k];
        R[L[k]]=R[k];
        for (int i=D[k];i!=k;i=D[i])
            for (int j=R[i];j!=i;j=R[j]){
                U[D[j]]=U[j];
                D[U[j]]=D[j];
                C[y[j]]--;
            }
    }
    void Reset(int k){
        L[R[k]]=k;
        R[L[k]]=k;
        for (int i=U[k];i!=k;i=U[i])
            for (int j=L[i];j!=i;j=L[j]){
                U[D[j]]=j;
                D[U[j]]=j;
                C[y[j]]++;
            }
    }
    bool solve(){
        if (R[0]==0)
            return true;
        anscnt++;
        int k=R[0];
        for (int i=R[k];i!=0;i=R[i])
            if (C[i]<C[k])
                k=i;
        Delete(k);
        for (int i=D[k];i!=k;i=D[i]){
            ans[anscnt]=x[i];
            for (int j=R[i];j!=i;j=R[j])
                Delete(y[j]);
            if (solve())
                return true;
            for (int j=L[i];j!=i;j=L[j])
                Reset(y[j]);
        }
        Reset(k);
        anscnt--;
        return false;
    }
}dlx;
const int L=15,n=10;
int Row;
char ch[L][L];
bool matched[12];
struct PIC{
    int x,y,i,j;
}built[N];
bool match(int x,int y,int i,int j){
    char CHAR=i+'A';
    for (int a=0;a<4;a++)
        for (int b=0;b<4;b++)
            if (p[i][j][a][b]&&(x+a>n||y+b>x+a||ch[x+a][y+b]!=CHAR))
                return 0;
    return 1;
}
bool nmatch(int x,int y,int i,int j){
    for (int a=0;a<4;a++)
        for (int b=0;b<4;b++)
            if (p[i][j][a][b]&&(x+a>n||y+b>x+a||ch[x+a][y+b]!='.'))
                return 0;
    return 1;
}
int hash(int a,int b){
    return a*(a-1)/2+b;
}
void build(int x,int y,int i,int j){
    Row++;
    built[Row].x=x;
    built[Row].y=y;
    built[Row].i=i;
    built[Row].j=j;
    int first=dlx.cnt+1;
    for (int a=0;a<4;a++)
        for (int b=0;b<4;b++)
            if (p[i][j][a][b])
                dlx.link(Row,hash(x+a,y+b));
    dlx.link(Row,55+i+1);
    dlx.L[first]=dlx.cnt;
    dlx.R[dlx.cnt]=first;
}
void addPIC(int x,int y,int i,int j){
    char CHAR=i+'A';
    for (int a=0;a<4;a++)
        for (int b=0;b<4;b++)
            if (p[i][j][a][b])
                ch[x+a][y+b]=CHAR;
}
int main(){
    for (int i=1;i<=n;i++)
        scanf("%s",ch[i]+1);
    dlx.init(55+12);
    memset(matched,0,sizeof matched);
    Row=0;
    for (int i=1;i<=n;i++)
        for (int j=1,imat=0;j<=i;imat=0,j++)
            for (int x=0;x<12&&!imat;x++)
                for (int y=0;y<z[x]&&!imat;y++)
                    if (match(i,j,x,y)){
                        matched[x]=imat=1;
                        build(i,j,x,y);
                    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=i;j++)
            for (int x=0;x<12;x++){
                if (matched[x])
                    continue;
                for (int y=0;y<z[x];y++)
                    if (nmatch(i,j,x,y))
                        build(i,j,x,y);
            }
    bool found=dlx.solve();
    if (!found)
        printf("No solution");
    else {
        for (int i=1;i<=dlx.anscnt;i++){
            int bh=dlx.ans[i];
            if (!matched[built[bh].i])
                addPIC(built[bh].x,built[bh].y,built[bh].i,built[bh].j);
        }
        for (int i=1;i<=n;puts(""),i++)
            for (int j=1;j<=i;j++)
                printf("%c",ch[i][j]);
    }
    return 0;
}

 

posted @ 2017-08-07 22:18  zzd233  阅读(639)  评论(0编辑  收藏  举报