题意:数独游戏,用零代表空格。
思路:从第一个空格开始深搜,遇到解便输出并退出。
版本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 0x3fffffff using 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; }