poj3074 DLX精确覆盖

题意:解数独

分析:

完整的数独有四个充要条件:

1.每个格子都有填数字

2.每列都有1~9中的每个数字

3.每行都有1~9中的每个数字

4.每个9宫格都有1~9中的每个数字

可以转化成精确覆盖问题。每行表示一个格子的一种填法,1~81列表示这个格子的位置,82~162列表示这是哪一行的什么数字,163~243列表示这是哪一列的什么数字,244~324列表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。

对于已经确定的点 我们就直接建一行 对于没有确定的点我们就 建k行(k<=9),这样说如果在该行该列或者该3*3的矩阵中存在该数字 则对应的该数字所在的行就没有必要建立了

这样跑一次dlx精确覆盖就ok了

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int M=9*9*9*10*4;

struct node{
   int c,x,y,k;
};
struct DLX
{
        int n,sz;
        int S[9*9*5];
        int row[M],col[M];
        int L[M],R[M],U[M],D[M];
        int ans[10][10];
        int X[M],Y[M],Cnt[M];
        void init(int n)
        {
            this->n=n;
            for(int i=0; i<=n; i++)
            {
                U[i]=i;D[i]=i;
                L[i]=i-1; R[i]=i+1;
            }
            R[n]=0;L[0]=n;
            sz=n+1;
            memset(S,0,sizeof(S));
        }
        void addRow(int r,vector<node>columns)
        {
            int first=sz;
            for(int i=0; i<columns.size();i++)
            {
                int c=columns[i].c; X[sz]=columns[i].x; Y[sz]=columns[i].y; Cnt[sz]=columns[i].k;
                L[sz]=sz-1;
                R[sz]=sz+1;
                D[sz]=c; U[sz]=U[c];
                D[U[c]]=sz;U[c]=sz;
                row[sz]=r;col[sz]=c;
                S[c]++;sz++;
            }
           R[sz-1]=first; L[first]=sz-1;
        }
        #define FOR(i,A,s) for(int i=A[s]; i!=s; i=A[i])
        void remove(int c)
        {
            L[R[c]]=L[c];
            R[L[c]]=R[c];
            FOR(i,D,c)
            FOR(j,R,i)
            {
                U[D[j]]=U[j];D[U[j]]=D[j];--S[col[j]];
            }
        }
        void restore(int c)
        {
            FOR(i,U,c)
            FOR(j,L,i)
            {
                ++S[col[j]];U[D[j]]=j;D[U[j]]=j;
            }
            L[R[c]]=c;
            R[L[c]]=c;
        }
        bool dfs(int d)
        {
            if(R[0]==0)return true;
            else
            {
                int num=R[0];
                FOR(i,R,0)
                {
                   if(S[i]==0) return false;
                   if(S[num]>S[i])
                    {
                        num=i;
                    }
                }
                remove(num);
                FOR(i,D,num)
                {
                    ans[X[i]][Y[i]]=Cnt[i];
                    FOR(j,R,i)remove(col[j]);
                    if(dfs(i+1))
                    {
                       return true;
                    }
                    FOR(j,L,i)restore(col[j]);
                }
                restore(num);
                return false;
            }
        }
}Link;
bool hasr[10][10],hasc[10][10],hasp[10][10];
char str[100];
vector<node> colum;
int main()
{
    while(scanf("%s",str)==1&&str[0]!=‘e‘)
    {
        memset(hasr,false,sizeof(hasr));
        memset(hasc,false,sizeof(hasc));
        memset(hasp,false,sizeof(hasp));
        for(int i=0; i<9; i++)
            for(int j=0; j<9; j++)
            {
                if(str[i*9+j]!=‘.‘)
                {
                    int k=str[i*9+j]-‘0‘;
                    hasr[i][k]=true;
                    hasc[j][k]=true;
                    hasp[i/3 *3+j/3][k]=true;
                }
            }
        int m=4*9*9;
        int n=0;
        Link.init(m);
        for(int i=0; i<9; i++)
            for(int j=0; j<9; j++)
            {
                int k=0;
                if(str[i*9+j]!=‘.‘)
                    k=str[i*9+j]-‘0‘;
                if(k!=0)
                {
                    n++;
                    colum.clear();
                    node dot;
                    dot.k=k;
                    dot.x=i;
                    dot.y=j;
                    dot.c=i*9+j+1;
                    colum.push_back(dot);
                    dot.c=81+i*9+k;
                    colum.push_back(dot);
                    dot.c=162+j*9+k;
                    colum.push_back(dot);
                    dot.c=243+(i/3*3+j/3)*9+k;
                    colum.push_back(dot);
                    Link.addRow(n,colum);
                }else {
                    node dot;
                    dot.x=i;dot.y=j;
                    for(int k=1; k<=9; k++)
                    {
                        if(hasr[i][k]==false &&hasc[j][k]==false && hasp[i/3*3+j/3][k]==false)
                        {
                            dot.k=k;
                            colum.clear();
                            n++;
                            dot.c=i*9+j+1;
                            colum.push_back(dot);
                            dot.c=81+i*9+k;
                            colum.push_back(dot);
                            dot.c=162+j*9+k;
                            colum.push_back(dot);
                            dot.c=243+(i/3*3+j/3)*9+k;
                            colum.push_back(dot);
                            Link.addRow(n,colum);
                        }
                    }

                }

            }
            Link.dfs(0);
            for(int i=0; i<9;i++)
               for(int j=0; j<9; j++)
                 printf("%d",Link.ans[i][j]);
            puts("");
    }
    return 0;
}

时间: 2024-10-13 05:16:35

poj3074 DLX精确覆盖的相关文章

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 . .

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

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

(简单) 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

zoj 3209.Treasure Map(DLX精确覆盖)

直接精确覆盖 开始逐行添加超时了,换成了单点添加 #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <vector> using namespace std; #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i]) #define exp 1e-8 const int MAX =

[DLX精确覆盖+打表] hdu 2518 Dominoes

题意: 就是给12种图形,旋转,翻折.有多少种方法构成n*m=60的矩形 思路: 裸的精确覆盖.就是建图麻烦 个人太挫,直接手写每一个图形的各种形态 须要注意的是最后的答案须要除以4 代码: #include"stdio.h" #include"algorithm" #include"string.h" #include"iostream" #include"queue" #include"map