暴力搜索
#include<stdio.h> #include<iostream> #include<fstream> using namespace std; int a[10][10]; int Max=0; int sudoku(int x,int y,bool *occupy)/* occupy为传递给函数的数组头指针*/ { int rx=x%3; int ry=y%3; int bx,by; if (rx==0) bx=x-2; else if (rx==1) bx=x; else if (rx==2) bx=x-1; if (ry==0) by=y-2; else if (ry==1) by=y; else if (ry==2) by=y-1; for (int i=bx;i<=bx+2;i++) for (int j=by;j<=by+2;j++) if (a[i][j]!=0) occupy[a[i][j]]=false; return 0; } int count() { int c=0; for(int i=1;i<10;i++) for (int j=1;j<10;j++) c+=a[i][j]*6; for(int i=2;i<9;i++) for (int j=2;j<9;j++) c+=a[i][j]; for(int i=3;i<8;i++) for (int j=3;j<8;j++) c+=a[i][j]; for(int i=4;i<7;i++) for (int j=4;j<7;j++) c+=a[i][j]; c+=a[5][5]; return c; } int dfs(int x,int y) { int xx,yy; if (x>9) { int c=count(); if (c>Max) Max=c; return 0; } if (a[x][y]!=0) { if (y<9) { xx=x; yy=y+1; } else { xx=x+1; yy=1; } dfs(xx,yy); } else { bool occupy[10];/*occupy[i]表示i是否可以填入*/ for (int i=1;i<10;i++) occupy[i]=true; for (int i=1;i<10;i++)/*坐标(x,y)所在列不能重复*/ if (a[i][y]!=0) occupy[a[i][y]]=false; for (int j=1;j<10;j++)/*坐标(x,y)所在行不能重复*/ if (a[x][j]!=0) occupy[a[x][j]]=false; sudoku(x,y,occupy);/*坐标(x,y)所在小九宫格不能重复*/ for (int i=9;i>0;i--) { if (occupy[i]) { a[x][y]=i; if (y<9) { xx=x; yy=y+1; } else { xx=x+1; yy=1; } dfs(xx,yy); a[x][y]=0; } } } return 0; } int main() { ifstream infile; infile.open("in.txt"); ofstream outfile; outfile.open("out.txt"); for (int i=1;i<=9;i++) for (int j=1;j<=9;j++) { int k; infile >> k; a[i][j]=k; } dfs(1,1); if (Max==0) outfile << -1 <<endl; else outfile << Max << endl; infile.close(); outfile.close(); return 0; }
优化1:位运算
#include<stdio.h> #include<iostream> #include<fstream> using namespace std; #define getid(i,j) ((i-1)/3*3+(j-1)/3+1) int a[10][10]; int r[10]; int c[10]; int sudoku[10]; int Max=0; int count() { int c=0; for(int i=1;i<10;i++) for (int j=1;j<10;j++) c+=a[i][j]*6; for(int i=2;i<9;i++) for (int j=2;j<9;j++) c+=a[i][j]; for(int i=3;i<8;i++) for (int j=3;j<8;j++) c+=a[i][j]; for(int i=4;i<7;i++) for (int j=4;j<7;j++) c+=a[i][j]; c+=a[5][5]; return c; } int dfs(int x,int y) { int xx,yy; if (x>9) { int c=count(); if (c>Max) Max=c; return 0; } if (a[x][y]!=0) { if (y<9) { xx=x; yy=y+1; } else { xx=x+1; yy=1; } dfs(xx,yy); } else { int k=r[x]|c[y]|sudoku[getid(x,y)]; for (int i=9;i>0;i--) { if (!((1<<(i-1))&k)) { a[x][y]=i; r[x]|=1<<(i-1); c[y]|=1<<(i-1); sudoku[getid(x,y)]|=1<<(i-1); if (y<9) { xx=x; yy=y+1; } else { xx=x+1; yy=1; } dfs(xx,yy); a[x][y]=0; r[x]^=1<<(i-1); c[y]^=1<<(i-1); sudoku[getid(x,y)]^=1<<(i-1); } } } return 0; } int main() { ifstream infile; infile.open("in.txt"); ofstream outfile; outfile.open("out.txt"); for (int i=1;i<=9;i++) for (int j=1;j<=9;j++) { infile >> a[i][j]; if (a[i][j]!=0) { r[i]|=1<<(a[i][j]-1); c[j]|=1<<(a[i][j]-1); sudoku[getid(i,j)]|=1<<(a[i][j]-1); } } dfs(1,1); if (Max==0) outfile << -1 <<endl; else outfile << Max << endl; infile.close(); outfile.close(); return 0; }
优化2:按照空白的格内可填的数字个数由小到大搜索
#include<stdio.h> #include<iostream> #include<fstream> using namespace std; #define getid(i,j) ((i-1)/3*3+(j-1)/3+1) int a[10][10]; int r[10]; int c[10]; int sudoku[10]; int Max=0; int count() { int c=0; for(int i=1;i<10;i++) for (int j=1;j<10;j++) c+=a[i][j]*6; for(int i=2;i<9;i++) for (int j=2;j<9;j++) c+=a[i][j]; for(int i=3;i<8;i++) for (int j=3;j<8;j++) c+=a[i][j]; for(int i=4;i<7;i++) for (int j=4;j<7;j++) c+=a[i][j]; c+=a[5][5]; return c; } int dfs(int x,int y) { int xx,yy; if (x>9) { int c=count(); if (c>Max) Max=c; return 0; } if (a[x][y]!=0) { if (y<9) { xx=x; yy=y+1; } else { xx=x+1; yy=1; } dfs(xx,yy); } else { int k=r[x]|c[y]|sudoku[getid(x,y)]; for (int i=9;i>0;i--) { if (!((1<<(i-1))&k)) { a[x][y]=i; r[x]|=1<<(i-1); c[y]|=1<<(i-1); sudoku[getid(x,y)]|=1<<(i-1); if (y<9) { xx=x; yy=y+1; } else { xx=x+1; yy=1; } dfs(xx,yy); a[x][y]=0; r[x]^=1<<(i-1); c[y]^=1<<(i-1); sudoku[getid(x,y)]^=1<<(i-1); } } } return 0; } int main() { ifstream infile; infile.open("in.txt"); ofstream outfile; outfile.open("out.txt"); for (int i=1;i<=9;i++) for (int j=1;j<=9;j++) { infile >> a[i][j]; if (a[i][j]!=0) { r[i]|=1<<(a[i][j]-1); c[j]|=1<<(a[i][j]-1); sudoku[getid(i,j)]|=1<<(a[i][j]-1); } } dfs(1,1); if (Max==0) outfile << -1 <<endl; else outfile << Max << endl; infile.close(); outfile.close(); return 0; }