推荐http://blog.csdn.net/hustspy1990/article/details/7464698
http://blog.csdn.net/linyunzju/article/details/7673959
http://blog.csdn.net/erorr/article/details/5902385
问题:
构造一个9*9的方格矩阵,玩家要在每个方格中,分别填上1至9的任意一个数字,
让整个棋盘每一列、每一行以及每一个3*3的小矩阵中的数字都不重复。
1. 回溯法-程序
/**回溯法
* 生成数独矩阵
* From 编程之美1.15
*/
#include <stdio.h>
#include <time.h>
/*要生成的数独矩阵个数*/
#define SUDOKU_NUM 1
/**
* 函数is_digital_match
* 检测sudoku[i][j]上的值是否符合要求
*/
int is_digital_match(int sudoku[][9], int i, int j)
{
int temp = sudoku[i][j];
int p, q;
int m, n;
for(p=0; p<9; p++)
if(p!=i && sudoku[p][j]==temp)
return 0;
for(p=0; p<9; p++)
if(p!=j && sudoku[i][p]==temp)
return 0;
p = i/3;
q = j/3;
for(m=p*3; m<p*3+3; m++)
for(n=q*3; n<q*3+3; n++)
if(m!=i && n!=j && sudoku[m][n]==temp)
return 0;
return 1;
}
/*输出数独矩阵*/
void sudoku_print(int sudoku[][9])
{
int i,j;
for(i=0; i<9; i++)
{
for(j=0; j<9; j++)
printf("%4d", sudoku[i][j]);
printf("\n");
}
}
int main(void)
{
int sudoku[9][9] = {0};
int i, j, temp=0;
int k=0, num=0;
srand(time(0));
for(i=0; i<9; i++)
for(j=0; j<9; j++)
sudoku[i][j] = 0;
/*通过添加一些随机性,来每次生成不同的数独矩阵*/
/*添加更多随机性,则生成的矩阵将更随即*/
for(i=0; i<9; i++)
{
temp = rand() % 81;
sudoku[temp/9][temp%9] = i+1;
}
/*回溯法,构造数独矩阵*/
while(1)
{
i = k/9;
j = k%9;
while(1)
{
sudoku[i][j]++;
if(sudoku[i][j] == 10)
{
sudoku[i][j] = 0;
--k;
break;
}
else if(is_digital_match(sudoku, i, j) == 1)
{
++k;
break;
}
}
if(k == 81)
{
printf("Proper sudoku matrix %d: \n", ++num);
sudoku_print(sudoku);
if(num >= SUDOKU_NUM)
return 0;
--k;
}
}
return 0;
}
输出结果:
Proper sudoku matrix 1:
2 1 4 5 6 7 9 3 8
3 5 7 1 8 9 2 4 6
6 8 9 4 2 3 1 5 7
4 2 1 3 7 5 8 6 9
8 6 3 2 9 1 4 7 5
7 9 5 6 4 8 3 1 2
5 3 6 8 1 2 7 9 4
1 7 8 9 5 4 6 2 3
9 4 2 7 3 6 5 8 1
2. 置换的方法
/**简单方法
* 快速的构造数独矩阵的算法
* From:编程之美1.15节
* 通过置换,来生成矩阵
*/
#include <stdio.h>
#include <time.h>
int main()
{
int ini_matrix[3][3]; /*最初的3*3的小格子,用于生成9*9的大格子*/
int sudoku[9][9] = {0};
int i,j;
for(i=0; i<3; i++)
{
for (j=0; j<3; j++)
{
ini_matrix[i][j] = i*3+j+1;
}
}
/*设置随机数种子*/
srand(time(0));
for(i=0; i<9; i++)
{
int temp = rand() % 9;
j = ini_matrix[i/3][i%3];
ini_matrix[i/3][i%3] = ini_matrix[temp/3][temp%3];
ini_matrix[temp/3][temp%3] = j;
}
printf("Initial matrix:\n");
for(i=0; i<3; i++)
{
for (j=0; j<3; j++)
{
printf("%d\t", ini_matrix[i][j]);
}
printf("\n");
}
/*Put the ini_matrix to the center of sudoku*/
for(i=0; i<3; i++)
{
for (j=0; j<3; j++)
{
sudoku[i+3][j+3] = ini_matrix[i][j];
if(i==0)
{
sudoku[i+4][j] = ini_matrix[i][j];
sudoku[i+5][j+6] = ini_matrix[i][j];
}
else if(i==1)
{
sudoku[i+4][j] = ini_matrix[i][j];
sudoku[i+2][j+6] = ini_matrix[i][j];
}
else
{
sudoku[i+1][j] = ini_matrix[i][j];
sudoku[i+2][j+6] = ini_matrix[i][j];
}
if(j==0)
{
sudoku[i][j+4] = ini_matrix[i][j];
sudoku[i+6][j+5] = ini_matrix[i][j];
}
else if(j==1)
{
sudoku[i][j+4] = ini_matrix[i][j];
sudoku[i+6][j+2] = ini_matrix[i][j];
}
else
{
sudoku[i][j+1] = ini_matrix[i][j];
sudoku[i+6][j+2] = ini_matrix[i][j];
}
}
}
for(i=3; i<6; i++)
{
for (j=0; j<3; j++)
{
if(j==0)
{
sudoku[i-3][j+1] = sudoku[i][j];
sudoku[i+3][j+2] = sudoku[i][j];
}
else if(j==1)
{
sudoku[i-3][j+1] = sudoku[i][j];
sudoku[i+3][j-1] = sudoku[i][j];
}
else
{
sudoku[i-3][j-2] = sudoku[i][j];
sudoku[i+3][j-1] = sudoku[i][j];
}
}
}
for(i=3; i<6; i++)
{
for (j=6; j<9; j++)
{
if(j==6)
{
sudoku[i-3][j+1] = sudoku[i][j];
sudoku[i+3][j+2] = sudoku[i][j];
}
else if(j==7)
{
sudoku[i-3][j+1] = sudoku[i][j];
sudoku[i+3][j-1] = sudoku[i][j];
}
else
{
sudoku[i-3][j-2] = sudoku[i][j];
sudoku[i+3][j-1] = sudoku[i][j];
}
}
}
printf("Final matrix:\n");
for(i=0; i<9; i++)
{
for (j=0; j<9; j++)
{
printf("%d\t", sudoku[i][j]);
}
printf("\n");
}
return 0;
}
输出结果:
Initial matrix:
3 5 7
2 6 4
8 9 1
Final matrix:
1 8 97 3 5 4 26
7 3 54 2 6 1 89
4 2 61 8 9 7 35
8 9 13 5 7 2 64
3 5 72 6 4 8 91
2 6 48 9 1 3 57
9 1 85 7 3 6 42
5 7 36 4 2 9 18
6 4 29 1 8 5 73
首先我们通过一个深度优先搜索来生成一个可行解,然后随机删除一定数量的数字,
以生成一个数独。
#include <iostream>
#include <cstdlib>
using namespace std;
#define LEN 9
#define CLEAR(a) memset((a), 0, sizeof(a))
int level[] = {30, 37, 45};
int grid[LEN+1][LEN+1];
int value[LEN+1];
void next(int &x, int &y)
{
x++;
if (x>9)
{
x = 1;
y++;
}
}
// 选择下一个有效状态
int pickNextValidValue(int x, int y, int cur)
{
CLEAR(value);
int i, j;
for (i=1; i<y; i++)
value[grid[i][x]] = 1;
for (j=1; j<x; j++)
value[grid[y][j]] = 1;
int u = (x-1)/3*3 + 1;
int v = (y-1)/3*3 + 1;
for (i=v; i<v+3; i++)
for (j=u; j<u+3; j++)
{
value[grid[i][j]] = 1;
}
for (i=cur+1; i<=LEN && value[i]; i++);
return i;
}
void pre(int &x, int &y)
{
x--;
if (x<1)
{
x = 9;
y--;
}
}
int times = 0;
int main()
{
int x, y, i, j;
x = y = 1;
// 深度搜索的迭代算法
while (true)
{
times++;
// 满足成功结果
if (y==LEN && x==LEN)
{
for (i=1; i<=LEN; i++)
{
for (j=1; j<=LEN; j++)
cout << grid[i][j] << " ";
cout << endl;
}
cout << times << endl;
break;
//pre(x, y);
//times = 0;
}
// 满足失败结果
if (y==0)
break;
// 改变状态
grid[y][x] = pickNextValidValue(x, y, grid[y][x]);
if (grid[y][x] > LEN)
{
// 恢复状态
grid[y][x] = 0;
pre(x, y);
}
else
// 进一步搜索
next(x,y);
}
for (i=1; i<= level[2]; i++)
{
int ind = rand()%(LEN*LEN);
grid[ind/LEN+1][ind%LEN] = 0;
}
for (i=1; i<=LEN; i++)
{
for (j=1; j<=LEN; j++)
cout << grid[i][j] << " ";
cout << endl;
}
}