[DLX精确覆盖] hdu 4210 Su-domino-ku

题意:

首先给你N块板(2*1或1*2)的,数字以及位置

再给你9个单个的板,1~9,分别的位置

然后问你如何放其他板(1*2或2*1)使得成为数独

注意的是对于板子来说,含有的数字是唯一的

也就是含有数字1和2的板有且只有1块

思路:

感觉自己太挫的,写了超级麻烦的建图

列是5*9*9的

前面的4*9*9就和普通的数独一样

后面的9*9是代表放的板的数字 就是对于(i,j)这的数对进行标记

当然需要特殊加入i==j的这些板子。

然后行就是前面的N块以及9个单块,还有9个特殊的

剩下的对于没有出现的数对进行枚举

接着对于能放的位置进行枚举

接着是横着放还是竖着放

这样建图。

代码:

#include"stdio.h"
#include"algorithm"
#include"string.h"
#include"iostream"
#include"queue"
#include"map"
#include"vector"
#include"string"
using namespace std;
#define N 14010*(4*9*9+9*9)
#define M 14010
struct DLX
{
    int n,m,C;
    int U[N],D[N],L[N],R[N],Row[N],Col[N];
    int H[M],S[M],cnt,ans[M];
    void init(int _n,int _m)
    {
        n=_n;
        m=_m;
        for(int i=0; i<=m; i++)
        {
            U[i]=D[i]=i;
            L[i]=(i==0?m:i-1);
            R[i]=(i==m?0:i+1);
            S[i]=0;
        }
        C=m;
        for(int i=1; i<=n; i++) H[i]=-1;
    }
    void link(int x,int y)
    {
        C++;
        Row[C]=x;
        Col[C]=y;
        S[y]++;
        U[C]=U[y];
        D[C]=y;
        D[U[y]]=C;
        U[y]=C;
        if(H[x]==-1) H[x]=L[C]=R[C]=C;
        else
        {
            L[C]=L[H[x]];
            R[C]=H[x];
            R[L[H[x]]]=C;
            L[H[x]]=C;
        }
    }
    void del(int x)
    {
        R[L[x]]=R[x];
        L[R[x]]=L[x];
        for(int i=D[x]; i!=x; 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 rec(int x)
    {
        for(int i=U[x]; i!=x; i=U[i])
        {
            for(int j=L[i]; j!=i; j=L[j])
            {
                U[D[j]]=j;
                D[U[j]]=j;
                S[Col[j]]++;
            }
        }
        R[L[x]]=x;
        L[R[x]]=x;
    }
    int dance(int x)
    {
        if(R[0]==0)
        {
            cnt=x;
            return 1;
        }
        int now=R[0];
        for(int i=R[0]; i!=0; i=R[i])
        {
            if(S[i]<S[now]) now=i;
        }
        del(now);
        for(int i=D[now]; i!=now; i=D[i])
        {
            ans[x]=Row[i];
            for(int j=R[i]; j!=i; j=R[j]) del(Col[j]);
            if(dance(x+1)) return 1;
            for(int j=L[i]; j!=i; j=L[j]) rec(Col[j]);
        }
        rec(now);
        return 0;
    }
} dlx;
struct node
{
    int a,b;
    int x,y,f;
} kx[M];
void getplace(int i,int j,int k,int &a,int &b,int &c)
{
    a=81+(i-1)*9+k;
    b=81*2+(j-1)*9+k;
    c=81*3+((i-1)/3*3+(j-1)/3)*9+k;
}
int main()
{
    int n,cas=1;
    while(scanf("%d",&n),n)
    {
        int mark[12][12],mp[12][12]; //mark标记哪些数对出现过
        memset(mp,0,sizeof(mp));
        memset(mark,0,sizeof(mark));
        int cnt=0;
        dlx.init(14000,5*9*9);
        for(int i=1; i<=n; i++)  //一开始给的N个板子
        {
            cnt++;
            int x,tep,d1,d2;
            char y[10];
            scanf("%d%s",&x,y);
            d1=x;
            mp[y[0]-'A'+1][y[1]-'0']=x;
            tep=(y[0]-'A')*9+y[1]-'0';
            int a,b,c;
            getplace(y[0]-'A'+1,y[1]-'0',x,a,b,c);
            dlx.link(cnt,tep);
            dlx.link(cnt,a);
            dlx.link(cnt,b);
            dlx.link(cnt,c);
            scanf("%d%s",&x,y);
            d2=x;
            mp[y[0]-'A'+1][y[1]-'0']=x;
            tep=(y[0]-'A')*9+y[1]-'0';
            getplace(y[0]-'A'+1,y[1]-'0',x,a,b,c);
            dlx.link(cnt,tep);
            dlx.link(cnt,a);
            dlx.link(cnt,b);
            dlx.link(cnt,c);
            mark[d1][d2]=mark[d2][d1]=1;
            dlx.link(cnt,81*4+(d1-1)*9+d2);
            dlx.link(cnt,81*4+(d2-1)*9+d1);
        }
        for(int i=1; i<=9; i++)  //加入单个板子
        {
            cnt++;
            char y[12];
            scanf("%s",y);
            mp[y[0]-'A'+1][y[1]-'0']=i;
            int tep=(y[0]-'A')*9+y[1]-'0';
            int a,b,c;
            getplace(y[0]-'A'+1,y[1]-'0',i,a,b,c);
            dlx.link(cnt,tep);
            dlx.link(cnt,a);
            dlx.link(cnt,b);
            dlx.link(cnt,c);
        }
        for(int i=1; i<=9; i++)   //加入特殊的板子
        {
            cnt++;
            dlx.link(cnt,81*4+(i-1)*9+i);
        }
        for(int i=1; i<=9; i++)
        {
            for(int j=1; j<=9; j++)
            {
                if(i==j) continue;
                if(mark[i][j]) continue;
                for(int xx=1; xx<=9; xx++)      //横放
                {
                    for(int yy=1; yy<=8; yy++)
                    {
                        cnt++;
                        kx[cnt].a=i;
                        kx[cnt].b=j;
                        kx[cnt].f=0;
                        kx[cnt].x=xx;
                        kx[cnt].y=yy;

                        int tep=(xx-1)*9+yy;
                        int a,b,c;
                        getplace(xx,yy,i,a,b,c);
                        dlx.link(cnt,tep);
                        dlx.link(cnt,a);
                        dlx.link(cnt,b);
                        dlx.link(cnt,c);

                        tep=(xx-1)*9+yy+1;
                        getplace(xx,yy+1,j,a,b,c);
                        dlx.link(cnt,tep);
                        dlx.link(cnt,a);
                        dlx.link(cnt,b);
                        dlx.link(cnt,c);

                        dlx.link(cnt,81*4+(i-1)*9+j);
                        dlx.link(cnt,81*4+(j-1)*9+i);

                    }
                }

                for(int xx=1; xx<=8; xx++)      //竖放
                {
                    for(int yy=1; yy<=9; yy++)
                    {
                        cnt++;
                        kx[cnt].a=i;
                        kx[cnt].b=j;
                        kx[cnt].f=1;
                        kx[cnt].x=xx;
                        kx[cnt].y=yy;

                        int tep=(xx-1)*9+yy;
                        int a,b,c;
                        getplace(xx,yy,i,a,b,c);
                        dlx.link(cnt,tep);
                        dlx.link(cnt,a);
                        dlx.link(cnt,b);
                        dlx.link(cnt,c);

                        tep=(xx)*9+yy;
                        getplace(xx+1,yy,j,a,b,c);
                        dlx.link(cnt,tep);
                        dlx.link(cnt,a);
                        dlx.link(cnt,b);
                        dlx.link(cnt,c);

                        dlx.link(cnt,81*4+(i-1)*9+j);
                        dlx.link(cnt,81*4+(j-1)*9+i);
                    }
                }
            }
        }
        dlx.dance(0);
        for(int i=0;i<dlx.cnt;i++)
        {
            //printf("%d\n",dlx.ans[i]);
            if(dlx.ans[i]>n+18)
            {
                int tep=dlx.ans[i];
                mp[kx[tep].x][kx[tep].y]=kx[tep].a;
                if(kx[tep].f==0) mp[kx[tep].x][kx[tep].y+1]=kx[tep].b;
                else mp[kx[tep].x+1][kx[tep].y]=kx[tep].b;
            }
        }
        printf("Puzzle %d\n",cas++);
        for(int i=1;i<=9;i++)
        {
            for(int j=1;j<=9;j++) printf("%d",mp[i][j]);
            puts("");
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-17 02:54:30

[DLX精确覆盖] hdu 4210 Su-domino-ku的相关文章

[DLX精确覆盖] hdu 3663 Power Stations

题意: 给你n.m.d,代表有n个城市,m条城市之间的关系,每个城市要在日后d天内都有电. 对于每个城市,都有一个发电站,每个发电站可以在[a,b]的每一个连续子区间内发电. x城市发电了,他相邻的城市也有电,并且每个发电站只能启动一次,或者不启动. 现在问,如何安排发电站的启动,保证每个城市d天都有电. 输出发电方案,不发电的话输出0 0 思路: 一个简单的精确覆盖问题,就是建图比较麻烦一点. 这里考虑到每天都要得到电,所以把每个城市每天都设为列(n*d) 然后每个城市对于[a,b]的所有子区

[DLX精确覆盖] hdu 1603 A Puzzling Problem

题意: 给你n块碎片,这些碎片不能旋转.翻折. 问你能不能用当中的某些块拼出4*4的正方形. 思路: 精确覆盖裸题了 建图就是看看每一个碎片在4*4中能放哪些位置,这个就作为行. 列就是4*4=16个位置再加上n个碎片也就是16+n 然后注意下成立的判定就好了 代码: #include"stdio.h" #include"algorithm" #include"string.h" #include"iostream" #inc

DLX精确覆盖与重复覆盖模板题

hihoCoder #1317 : 搜索四·跳舞链 原题地址:http://hihocoder.com/problemset/problem/1317 时间限制:10000ms 单点时限:1000ms 内存限制:256MB   描述 小Ho最近遇到一个难题,他需要破解一个棋局. 棋局分成了n行,m列,每行有若干个棋子.小Ho需要从中选择若干行使得每一列有且恰好只有一个棋子. 比如下面这样局面: 其中1表示放置有棋子的格子,0表示没有放置棋子. 对于上面这个问题,小Ho经过多次尝试以后得到了解为选

POJ 3047 Sudoku DLX精确覆盖

DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8336   Accepted: 2945 Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . .

ZOJ 3209 Treasure Map(DLX精确覆盖)

Your boss once had got many copies of a treasure map. Unfortunately, all the copies are now broken to many rectangular pieces, and what make it worse, he has lost some of the pieces. Luckily, it is possible to figure out the position of each piece in

POJ 3076 Sudoku DLX精确覆盖

DLX精确覆盖模版题..... Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 4416   Accepted: 2143 Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells are filled with letters from A to P (the fi

POJ 3074 Sudoku DLX精确覆盖

DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8336   Accepted: 2945 Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . .

(简单) HUST 1017 Exact cover , DLX+精确覆盖。

Description There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find out the selected rows. DLX精确覆盖的模板题...... 代码如下: //HUST 1

(简单) POJ 3074 Sudoku, DLX+精确覆盖。

Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . . . 6 7 3 5 . . . . . . . 2 9 3 . 5 6 9 2 . 8 . . . . . . . . . . . 6 . 1 7 4 5 . 3 6 4 . . . . . . . 9 5 1