数独游戏 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: $

 

 

 

江西理工大学 Fangshenghui 2010-5-1

posted @ 2010-05-01 17:24  xyecho  阅读(4239)  评论(3编辑  收藏  举报