C++ 数独游戏(回溯)



C++ 数独游戏(回溯)

数独游戏的规则:

1 每个数字在每一行只能出现一次

2 每个数字在每一列只能出现一次

3 每个数字在每一区只能出现一次

下面的input.txt是一个例子的约束条件 第一列表示每一个数所在的行 第二列表示每一个数所在的列,第三个这个位置上的值。

Input.txt

1 1 7

1 4 1

1 8 8

1 9 3

2 1 4

2 3 2

2 5 7

2 6 3

3 4 4

3 5 5

3 8 2

3 9 7

4 3 7

4 7 3

4 8 1

4 9 2

5 2 4

5 3 3

5 4 8

6 3 5

6 5 9

7 2 2

7 3 1

7 5 8

8 2 3

8 4 2

8 6 1

8 7 8

9 7 2

9 8 6

9 9 1

一 回溯法

 

复制代码
//============================================

#include <iostream>

#include <stdio.h>

using namespace std;

 

int State[9][9];

///——————————

void InitState()

{

for (int i=0; i<9; i++)

{

for (int j=0; j<9;j++)

{

State[i][j] = 0;

}

}

}

 

//——————————-

 

void Load()

{

freopen(“input.txt”,”r”,stdin); //输入从input.txt

int x, y, value;

int temp = 0;

while (scanf (“%d %d %d”, &x, &y, &value) != EOF)

{

State[x-1][y-1] = value;

}

}

 

//———————————

//检查每一个小区内只能出现一次

bool ChechZone(int x, int y, int i)

{

int xZone = 3 * (x / 3); //找到每个小区的位置

int yZone = 3 * (y / 3);

 

int j = 0;

int k = 0;

bool flag = true;

for (j=xZone; j<xZone+3; j++) //遍历小区的三行三列

{

for (k=yZone; k<yZone+3; k++)

{

//if (x == j && y == k)

//{

// continue;

//}

 

if ((x != j || y != k) && State[j][k] == i)

{

flag = false;

goto A1;

}

}

}

A1:

return flag;

}

 

//——————————–

//检查是否符合条件

bool ChechAssign(int x, int y, int i)

{

bool flag = true;

for (int k=0; k<9; k++)

{

if (k != y && i == State[x][k] )

{

flag = false;

}

 

if (k != x && i == State[k][y] )

{

flag = false;

}

if (!ChechZone(x, y, i))

{

flag = false;

}

}

return flag;

}

///——————————

int Search (int depth)

{

if (depth >= 81)

{

//return Chech();

return 1;

}

 

int x, y;

x = depth / 9 ;

y = depth % 9 ;

 

//检查x y有没有被 赋值

if (0 != State[x][y])

{

return Search (depth + 1);

}

else //尝试赋值

{

for (int i=1; i<=9; i++)

{

//检查是否违反约束条件

State[x][y] = i;

if (ChechAssign(x, y, i))

{

if (Search(depth + 1))

{

return 1;

}

}

State[x][y] = 0;

}

return 0;

}

}

 

///—————————————

void OutputState()

{

for (int i=0; i<9; i++)

{

for (int j=0; j<9; j++)

{

cout << State[i][j] << ” “;

if (0 == (j+1) % 3)

{

cout << ” “;

}

}

 

if (0 == (i + 1) % 3)

{

cout << endl;

}

cout << endl;

}

cout << endl;

}

 

 

 

//————————————-

int main ()

{

cout << “=======初始化========”<< endl << endl;

InitState();

//输入函数

Load();

OutputState();

cout << “=======结果为=======”<< endl << endl;

//搜索

if (Search(0))

{

OutputState();

}

else

{

//输出提示信息

cout << “搜索失败!!!”<< endl;

}

cout << “====================”<< endl << endl;

return 0;

}

复制代码

 

 

二 优化后的回溯

就是先排序后再回溯 排序的依据是:先算出第一个空格的所在行各所在列对他的约束的个数。然后从大到小进行排序。

优化后的程序如下:

 

复制代码
#include <iostream>

#include <stdio.h>

using namespace std;

 

// ————————————————————————-

 

int State[9][9];

int StateSort[81][3]; //记录每个空元素的所在行列已有的数字个数 非空元素为0

 

void Print()

{

for (int i=0; i<81; i++)

{

for (int j=0; j<3; j++)

{

cout << StateSort[i][j] << ” “;

}

cout << endl;

}

}

 

///——————————

void InitState()

{

int i, j;

for (i=0; i<9; i++) //初始化State

{

for (j=0; j<9;j++)


{

State[i][j] = 0;

}

}

 

for (i=0; i<81; i++) // 初始化StateSort

{

StateSort[i][0] = i / 9 + 1;

StateSort[i][1] = i % 9 + 1;

StateSort[i][2] = 0;

}

// Print();

}

 

//——————————-

void Load()

{

freopen(“input.txt”,”r”,stdin); //输入从input.txt

int x, y, value;

while (scanf (“%d %d %d”, &x, &y, &value) != EOF)

{

State[x-1][y-1] = value;

}

}

 

//———————————

void Count()// 算出每一个空元素的所在行和列约束的个数

{

int k;

for (int i=0; i<9; i++)

{

for (int j=0; j<9; j++)

{

if (State[i][j] == 0)

{

int nCount = 0;

for (k=0; k<9; k++)

{

if ( 0 != State[i][k])

{

nCount++;

}

}

for (k=0; k<9; k++)

{

if (0 != State[k][j])

{

nCount++;

}

}

StateSort[i*9+j][2] = nCount;

}

 

}

}

}

 

//———————————————

void Sort()

{

int pivotkey[3] ;

for (int i=1; i<=81;i++)

{

if (StateSort[i][2] > StateSort[i-1][2])

{

pivotkey[2] = StateSort[i][2];

pivotkey[1] = StateSort[i][1];

pivotkey[0] = StateSort[i][0];

 

for (int j=i-1; (pivotkey[2]>StateSort[j][2]) && (j>=0); –j)

{

StateSort[j+1][2] = StateSort[j][2];

StateSort[j+1][1] = StateSort[j][1];

StateSort[j+1][0] = StateSort[j][0];

}

StateSort[j+1][2] = pivotkey[2];

StateSort[j+1][1] = pivotkey[1];

StateSort[j+1][0] = pivotkey[0];

}

}

//Print();

}

 

//———————————

//检查每一个小区内只能出现一次

bool ChechZone(int x, int y, int i)

{

int xZone = 3 * (x / 3); //找到每个小区的位置

int yZone = 3 * (y / 3);

 

int j = 0;

int k = 0;

bool flag = true;

for (j=xZone; j<xZone+3; j++) //遍历小区的三行三列

{

for (k=yZone; k<yZone+3; k++)

{

if ((x != j || y != k) && State[j][k] == i)

{

flag = false;

goto A1;

}

}

}

A1:

return flag;

}

 

//——————————–

//检查是否符合条件

bool ChechAssign(int x, int y, int i)

{

bool flag = true;

for (int k=0; k<9; k++)

{

if (k != y && i == State[x][k] )

{

flag = false;

}

 

if (k != x && i == State[k][y] )

{

flag = false;

}

if (!ChechZone(x, y, i))

{

flag = false;

}

}

return flag;

}

//———————————–

int DCount ()

{

int g_Count = 0;

for (int i=0; i<81; i++)

{

if (0 != StateSort[i][2])

{

g_Count++;

}

}

return g_Count;

}

 

 

///——————————-

 

int Search (int depth)

{

if (depth >= DCount())

{

return 1;

}

 

int x, y;

x = StateSort[depth][0] – 1;

y = StateSort[depth][1] – 1;

 

//检查x y有没有被 赋值

if (0 != State[x][y])

{

return Search (depth + 1);

}

else //尝试赋值

{

for (int i=1; i<=9; i++)

{

State[x][y] = i;

//检查是否违反约束条件

if (ChechAssign(x, y, i))

{

if (Search(depth + 1))

{

return 1;

}

}

State[x][y] = 0;

}

return 0;

}

}

 

///—————————————

void OutputState()

{

for (int i=0; i<9; i++)

{

for (int j=0; j<9; j++)

{

cout << State[i][j] << ” “;

if (0 == (j+1) % 3)

{

cout << ” “;

}

}

 

if (0 == (i + 1) % 3)

{

cout << endl;

}

cout << endl;

}

cout << endl;

}

 

//————————————-

int main ()

{

cout << “=======初始化========”<< endl << endl;

InitState();

//输入函数

Load();

OutputState();

//计算每个元素所在行列已有的数字个数 非空元素为0

Count();

//Print();

//cout <<”+++++++++”<<endl;

//排序

Sort();

//Print();

 

cout << “The Depth : ” << DCount() << endl <<endl;

cout << “=======结果为=======”<< endl << endl;

//搜索

if (Search(0))

{

//输出

OutputState();

}

else

{

//输出提示信息

cout << “搜索失败!!!”<< endl;

}

cout << “====================”<< endl << endl;

cout << DCount();

return 0;

}

// ————————————————————————-

// $Log: $

复制代码

http://www.cnblogs.com/fangshenghui/archive/2010/05/01/1725691.html