PKU3074 DLX版 数独建01矩阵

来源:互联网 发布:黑客编程入门3pdf 编辑:程序博客网 时间:2024/05/22 15:14


行数为9*9*9 代表9行9列每个格子9种情况,如果当前格子有数则只建一行

列约束为 9*9+9*9+9*9+9*9

分别为行9数,列9数,9*9的格子每个格子一个数,3*3的格子9个每个格子一个数

#define DeBUG#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <string>#include <set>#include <sstream>#include <map>#include <list>#include <bitset>using namespace std ;#define zero {0}#define INF 0x3f3f3f3f#define EPS 1e-6#define TRUE true#define FALSE falsetypedef long long LL;const double PI = acos(-1.0);//#pragma comment(linker, "/STACK:102400000,102400000")inline int sgn(double x){    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}#define N 3267//每个1占用一个编码+列数 m+9*9*9*4const int head = 0;int mat[750][350], tor[750], toc[750], dig[750];char str[100];int n, m, size, o[1010], s[750], col[N], row[N], u[N], d[N], l[N], r[N];//将输入条件转化为01矩阵。bool makegragh(){    int strnum, i, j, k, qua, pos, num;    scanf("%s", str);//输入    if (strcmp(str, "end") == 0)return false;    memset(mat, 0, sizeof(mat));//建图    n = 1; m = 324; strnum = 0;//初始化行列值    for (i = 1; i <= 9; i++)    {        for (j = 1; j <= 9; j++)        {            qua = (j - 1) / 3 * 3 + (i - 1) / 3 + 1;//            pos = (i - 1) * 9 + j;            if (str[strnum] == '.')            {                for (k = 1; k <= 9; k++)                {                    tor[n] = i;                    toc[n] = j;                    dig[n] = k;                    mat[n][(i - 1) * 9 + k] = 1;                    mat[n][81 + (j - 1) * 9 + k] = 1;                    mat[n][162 + (qua - 1) * 9 + k] = 1;                    mat[n++][243 + pos] = 1;                }            }            else            {                tor[n] = i;                toc[n] = j;                num = str[strnum] - '0';                dig[n] = num;                mat[n][(i - 1) * 9 + num] = 1;                mat[n][81 + (j - 1) * 9 + num] = 1;                mat[n][162 + (qua - 1) * 9 + num] = 1;                mat[n++][243 + pos] = 1;            }            strnum++;        }    }    n--;    return true;}void Link(int i, int j, int &rowh){    s[j]++;    u[size] = u[j];    d[u[j]] = size;    u[j] = size;    d[size] = j;    row[size] = i;    col[size] = j;    if (rowh == -1)    {        l[size] = r[size] = size;        rowh = size;    }    else    {        l[size] = l[rowh];        r[l[rowh]] = size;        r[size] = rowh;        l[rowh] = size;    }    size++;}//将01矩阵转化为十字链表,cnt表示结点个数,01矩阵是n行m列的。void initial(){    int i, j, rowh;    memset(s, 0, sizeof(s));    for (i = head; i <= m; i++)    {        r[i] = (i + 1) % (m + 1);        l[i] = (i - 1 + m + 1) % (m + 1);        u[i] = d[i] = i;    }    size = m + 1;    for (i = 1; i <= n; i++)    {        rowh = -1;        for (j = 1; j <= m; j++)            if (mat[i][j])            {                Link(i, j, rowh);            }    }    // printf("size=%d\n", size);}//删除矩阵中的列及其相应的行void myremove(const int &cur){    l[r[cur]] = l[cur];    r[l[cur]] = r[cur];    for (int i = d[cur]; i != cur; 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]];        }    }}//恢复。顺序和remove相反void myresume(const int &cur){    for (int i = u[cur]; i != cur; i = u[i])    {        for (int j = l[i]; j != i; j = l[j])        {            ++s[col[j]];            u[d[j]] = j;            d[u[j]] = j;        }    }    l[r[cur]] = cur;    r[l[cur]] = cur;}//最原始版本,只需输出一组合法解bool dfs(const int &k){    if (r[head] == head) //不需判断k是否等于N    {        sort(o, o + k);        for (int i = 0; i < k; i++)            printf("%d", dig[o[i]]);        printf("\n");        return true;    }    int ms = INF, cur = 0;    for (int t = r[head]; t != head; t = r[t])    {        if (s[t] < ms)        {            ms = s[t];            cur = t;        }    }    myremove(cur);    for (int i = d[cur]; i != cur; i = d[i])    {        o[k] = row[i];        for (int j = r[i]; j != i; j = r[j])            myremove(col[j]);        if (dfs(k + 1))return true;        for (int j = l[i]; j != i; j = l[j])            myresume(col[j]);    }    myresume(cur);    return false;}int main(){#ifdef DeBUGs    freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);#endif    while (makegragh())    {        initial();        dfs(0);    }    return 0;}


0 0