poj 2676 dfs/DLX(数独)

来源:互联网 发布:海康门禁软件 编辑:程序博客网 时间:2024/05/17 22:56

题意:数独游戏,用零代表空格。

思路:从第一个空格开始深搜,遇到解便输出并退出。

版本1:直接深搜,每次尝试解时逐行,逐列,逐块判断该解是否成立。费时间比较多。

版本2:开三个二维数组记录第i行(列、块)是否已经填入了数字j,则每次判断只需按照数组值来进行判断即可。所需时间比版本1要好。

版本3:用DLX则0ms刷过~

输入:

1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107

输出:

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127

#include <stdio.h>char in[10][10];int s[10][10];int T;void print(){int i,j;for(i = 0;i<9;i++){for(j = 0;j<9;j++)printf("%d",s[i][j]);putchar('\n');}}int check(int x,int y,int num){//判断在x行y列处填入num是否合法int i,j;for(i = 0;i<9;i++)if(s[x][i]==num || s[i][y]==num)return 0;for(i = x/3*3;i<3+x/3*3;i++)for(j = y/3*3;j<3+y/3*3;j++)if(s[i][j] == num)return 0;return 1;}int dfs(int index){int i,x,y;if(index == 81){//表示得到解,输出print();return 1;}x = index/9;y = index%9;if(s[x][y])//如果此位置初始填入了数字,直接搜下一位置return dfs(index+1);else{for(i = 1;i<=9;i++)if(check(x,y,i)){s[x][y] = i;if(dfs(index+1))return 1;}s[x][y] = 0;//此位置尝试遍都无解,务必将此位置归零}return 0;}int main(){freopen("a.txt","r",stdin);scanf("%d",&T);while(T--){int i,j;getchar();for(i = 0;i<9;i++)scanf("%s",in[i]);for(i = 0;i<9;i++)for(j = 0;j<9;j++)s[i][j] = in[i][j]-'0';dfs(0);}}

版本2:

#include <cstdio>#include <string>#include <vector>#include <iostream>#include <cstdlib>#include <cmath>using namespace std;int s[10][10],blank[81][2],num;int r[9][10],c[9][10],b[9][10];int T;int block(int i,int j){    return i/3*3 + j/3;}void setflag(int i,int j,int x,int yn){    r[i][x] = yn;    c[j][x] = yn;    b[block(i,j)][x] = yn;}int check(int x,int y,int w){    return !r[x][w] && !c[y][w] && !b[block(x, y)][w];}int dfs(int d){    int x,y,i;    x = blank[d][0];    y = blank[d][1];    if(d==num)        return 1;    for(i = 1;i<=9;i++)        if(check(x,y,i)){            s[x][y] = i;            setflag(x, y, i, 1);            if(dfs(d+1))                return 1;            setflag(x, y, i, 0);        }    return 0;}int main(){    scanf("%d",&T);    while(T--){        int i,j;        char ch;        num = 0;        memset(s, 0, sizeof(s));        memset(r, 0, sizeof(r));        memset(c, 0, sizeof(c));        memset(b, 0, sizeof(b));        for(i = 0;i<9;i++){            getchar();            for(j = 0;j<9;j++){                ch = getchar();                if(ch-'0'){                    s[i][j] = ch-'0';                    setflag(i,j,ch-'0',1);                }else{                    blank[num][0] = i;                    blank[num++][1] = j;                }            }        }        dfs(0);        for(i = 0;i<9;i++){            for(j = 0;j<9;j++)                printf("%d",s[i][j]);            putchar('\n');        }    }    return 0;}

DLX:

#include <cstdio>#include <cstring>#include <cmath>#define L 9#define N L*L*L#define M L*L*4#define OFFSET L*L#define INF 0x3fffffffusing namespace std;struct node{    int l,r,u,d,t,x,y,c;}p[N*4+M+5];int cnt[M+5],top,T;char tmp[L+5][L+5];int res[L+2][L+2];void init(){    memset(cnt, 0, sizeof(cnt));    for(int i = 0;i<=M;i++){        p[i].l = i-1;        p[i].r = i+1;        p[i].u = p[i].d = p[i].c = i;    }    p[0].l = M;    p[M].r = 0;    top = M;}int block(int i,int j){    int x = (int)sqrt((double)L);    return (i-1)/x*x + (j-1)/x;}void add(int l,int x,int y,int t,int c){    p[++top].x = x;    p[top].y = y;    p[top].t = t;    p[top].l = l;    p[p[top].l].r = top;    p[top].u = p[c].u;    p[p[top].u].d = top;    p[c].u = top;    p[top].d = p[top].c = c;    cnt[c]++;}void addp(int i,int j,int k){    add(top+4,i,j,k,(i-1)*L+j);    add(top, i, j, k, OFFSET+(i-1)*L+k);    add(top, i, j, k, OFFSET*2+(j-1)*L+k);    add(top, i, j, k, OFFSET*3+block(i,j)*L+k);}void del(int c){    int i,j;    p[p[c].l].r = p[c].r;    p[p[c].r].l = p[c].l;    for(i = p[c].d;i!=c;i=p[i].d)        for(j = p[i].r;j!=i;j=p[j].r){            p[p[j].u].d = p[j].d;            p[p[j].d].u = p[j].u;            cnt[p[j].c]--;        }}void re(int c){    int i,j;    p[p[c].l].r = c;    p[p[c].r].l = c;    for(i = p[c].d;i!=c;i=p[i].d)        for(j = p[i].r;j!=i;j=p[j].r){            p[p[j].u].d = j;            p[p[j].d].u = j;            cnt[p[j].c]++;        }}int dfs(){    int i,j,min = INF,c=0;    if(!p[0].r)        return 1;    for(i = p[0].r;i;i=p[i].r)        if(cnt[i] < min){            min = cnt[i];            c = i;        }    del(c);    for(i = p[c].d;i!=c;i=p[i].d){        res[p[i].x][p[i].y] = p[i].t;        for(j = p[i].r;j!=i;j=p[j].r)            del(p[j].c);        if(dfs())            return 1;        for(j = p[i].l;j!=i;j=p[j].l)            re(p[j].c);    }    re(c);    return 0;}int main(){    scanf("%d",&T);    while(T--){        int i,j,k,now=-1;        init();        for(i = 1;i<=L;i++){            getchar();            for(j = 1;j<=L;j++){                tmp[i][j] = getchar();            }        }        for(i = 1;i<=L;i++)            for(j = 1;j<=L;j++){                if(tmp[i][j] == '0')                    for(k = 1;k<=L;k++)                        addp(i,j,k);                else                    addp(i,j,tmp[i][j]-'0');            }        dfs();        for(i = 1;i<=L;i++){            for(j = 1;j<=L;j++)                printf("%d",res[i][j]);            putchar('\n');        }        putchar('\n');    }    return 0;}


0 0
原创粉丝点击