数独的求解算法 回溯

/*

数独的算法,有说用深度优先的,有说用dancing links(双向链表),这些技术不太熟,先用数组实现吧,

时间复杂度大了点,求解思路要优化下


0,9,0, 0,0,2, 0,0,1,
0,0,0, 0,6,0, 0,0,2,
0,0,0, 0,0,0, 4,0,0,
6,0,0, 0,8,0, 0,0,0,
0,2,0, 0,0,0, 0,0,0,
0,0,1, 7,0,4, 0,0,0,
3,6,0, 0,0,0, 0,0,0,
0,0,7, 0,0,0, 5,0,0,
9,5,0, 0,0,7, 0,0,8 

*/

// sudokuadv.cpp : 定义控制台应用程序的入口点。

//

//二维数组的回溯


#include "stdafx.h"
#include <iostream>
using namespace std;


char str[9][10];


int jiaquanArr[10]={0,1,2,4,8,16,32,64,128,256};


int   sudokuArr[9][9]={
0,9,0, 0,0,2, 0,0,1,//1 2 9
0,0,0, 0,6,0, 0,0,2,//2 6
0,0,0, 0,0,0, 4,0,0,//4
6,0,0, 0,8,0, 0,0,0,//6 8
0,2,0, 0,0,0, 0,0,0,//2
0,0,1, 7,0,4, 0,0,0,//1 4 7
3,6,0, 0,0,0, 0,0,0,//3 6
0,0,7, 0,0,0, 5,0,0,//5 7
9,5,0, 0,0,7, 0,0,8 //5 7 8 9
};




int sudokuright[9][9]=
{
4, 9, 5,  3, 7, 2,  6, 8, 1,
1, 7, 3,  4, 6, 8,  9, 5, 2,
2, 8, 6,  1, 9, 5,  4, 3, 7
};


/*
4 9 5  3 7 2  6 8 1
1 7 3  4 6 8  9 5 2
2 8 6  1 9 5  4 3 7


6 4 9  5 8 1  2 7 3
7 2 8  9 3 6  1 4 5
5 3 1  7 2 4  8 6 9


3 6 2  8 5 9  7 1 4
8 1 7  2 4 3  5 9 6
9 5 4  6 1 7  3 2 8
*/


bool bsudokuArr[9][9]={true};


//散列表,判断[1,9]取值能不能用,默认为true,用于辅助重复判断
bool bLiechongfuArr[9][10]={
{false,true,true,true,true,true,true,true,true,true},//第零列,  
{false,true,true,true,true,true,true,true,true,true},//第一列
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true}//第八列
};




//散列表,判断[1,9]取值能不能用,默认为true,用于辅助重复判断
bool bHangchongfuArr[9][10]={
{false,true,true,true,true,true,true,true,true,true},//第零行,  
{false,true,true,true,true,true,true,true,true,true},//第一行
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true},
{false,true,true,true,true,true,true,true,true,true}//第八行
};


bool IsPassCheckLineAndRow(int &line, int &row)
{
if(row<0 && line==0)
return false;
if(row < 0  &&  line>0)
{
row=8;
line--;
}
if(row > 8 && line<8)
{
row=0;
line++;
}
return true;


}
void ProductAllBsudokuArr(int   sudokuArr[9][9], bool bsudokuArr[9][9])
{
int const MaxHang=9;
int const MaxLie=9;
int temp;
for(int i=0; i<MaxHang; i++)
{
for(int j=0; j<MaxLie; j++)
{
temp=sudokuArr[i][j];


if(temp != 0)
{
bsudokuArr[i][j]=false;
bHangchongfuArr[i][temp]=false;
bLiechongfuArr[j][temp]=false;
}
else
{
bsudokuArr[i][j]=true;
}


}
}
}


bool IsPassHangChongFu(int a[9][9], int line, int row, int shitanzhi)
{
if(bHangchongfuArr[line][shitanzhi])
return true;
else
return false;
}


bool IsPassLieChongFu(int a[9][9], int line, int row, int shitanzhi)
{
if(bLiechongfuArr[row][shitanzhi])
return true;
else
return false;
}


bool IsPassJiuGong(int a[9][9],int line,int row,int shitanzhi)
{
bool lab=true;
int i,j;
int sumzuo,sumzhong,sumyou;
sumzuo=sumzhong=sumyou=0;
for(i=line-2; i<line; i++)
{
sumzuo  +=(jiaquanArr[  a[i][0] ]+jiaquanArr[  a[i][1] ]+jiaquanArr[  a[i][2] ]);
sumzhong+=(jiaquanArr[  a[i][3] ]+jiaquanArr[  a[i][4] ]+jiaquanArr[  a[i][5] ]);
sumyou  +=(jiaquanArr[  a[i][6] ]+jiaquanArr[  a[i][7] ]+jiaquanArr[  a[i][8] ]);
}


sumzuo  +=(jiaquanArr[  a[line][0] ]+jiaquanArr[  a[line][1] ]+jiaquanArr[  a[line][2] ]);
sumzhong+=(jiaquanArr[  a[line][3] ]+jiaquanArr[  a[line][4] ]+jiaquanArr[  a[line][5] ]);
sumyou  +=(jiaquanArr[  a[line][6] ]+jiaquanArr[  a[line][7] ]+jiaquanArr[  shitanzhi  ]);//这一个特殊点, a[line][8]还未有效





if(   (511==sumzuo)
&&(511==sumzhong)
&&(511==sumyou)
)
return true;
else
return false;
}


void ProductSudokuJie()
{
int t;
int count=0;
int line, row, shitanzhi;
int a[9][9];


for(line=0; line<9; line++)
{
for(row=0; row<9; row++)
{
a[line][row]=sudokuArr[line][row];//预设固定值
}
}


a[0][0]=4;//4是a[0][0]第一个可用值
//更新bLiechongfuArr和bHangchongfuArr
bHangchongfuArr[0][ a[0][0] ]=false;
bLiechongfuArr[0][ a[0][0] ]=false;


line =0;
row =1;
shitanzhi=1;
while(true)
{





if(line == 1  && row==2)
t=0;


if(line == 0 && row<0)
break;




if(line == 8 && row>8)
{
//输出可能解或统计
count++;


row--;if(!IsPassCheckLineAndRow(line,row))  break;
 
while(bsudokuArr[line][row] == false)//sudoku数组中,该元素为固定值
{
row--;if(!IsPassCheckLineAndRow(line,row))  break;
}
if(!IsPassCheckLineAndRow(line,row))  break;


shitanzhi=a[line][row]+1;


//更新bLiechongfuArr和bHangchongfuArr
bHangchongfuArr[line][ a[line][row] ]=true;
bLiechongfuArr[row][ a[line][row] ]=true;
}


if(shitanzhi > 9)
{
row--;if(!IsPassCheckLineAndRow(line,row))  break;


while(bsudokuArr[line][row] == false)//sudoku数组中,该元素为固定值
{
row--;if(!IsPassCheckLineAndRow(line,row))  break;
}
if(!IsPassCheckLineAndRow(line,row))  break;


shitanzhi=a[line][row]+1;


//更新bLiechongfuArr和bHangchongfuArr
bHangchongfuArr[line][ a[line][row] ]=true;
bLiechongfuArr[row][ a[line][row] ]=true;
}
else
{
if(bsudokuArr[line][row] == false)//sudoku数组中,该元素为固定值
{
if(  (line ==2 && row==8)
||(line ==5 && row==8)
||(line ==8 && row==8)
)
{
if(IsPassJiuGong(a, line, row, a[line][row]))//通过九宫检测
{
shitanzhi=1;
row++;IsPassCheckLineAndRow(line,row);
}
else
{
row--;if(!IsPassCheckLineAndRow(line,row))  break;


while(bsudokuArr[line][row] == false)//sudoku数组中,该元素为固定值
{
row--;if(!IsPassCheckLineAndRow(line,row))  break;
}
if(!IsPassCheckLineAndRow(line,row))  break;


shitanzhi=a[line][row]+1;


//更新bLiechongfuArr和bHangchongfuArr
bHangchongfuArr[line][ a[line][row] ]=true;
bLiechongfuArr[row][ a[line][row] ]=true;
}
}
else
{
shitanzhi=1;
row++;IsPassCheckLineAndRow(line,row);
}

}
else
{
if(IsPassHangChongFu(a, line, row, shitanzhi) && IsPassLieChongFu(a, line, row, shitanzhi))
{

if(  (line ==2 && row==8)
||(line ==5 && row==8)
||(line ==8 && row==8)
)
{


if(IsPassJiuGong(a, line, row, shitanzhi))//九宫判定
{
a[line][row]=shitanzhi;


//更新bLiechongfuArr和bHangchongfuArr
bHangchongfuArr[line][ a[line][row] ]=false;
bLiechongfuArr[row][ a[line][row] ]=false;



shitanzhi=1;
row++;IsPassCheckLineAndRow(line,row);
}
else
{
shitanzhi++;
}
}
else
{
a[line][row]=shitanzhi;


//更新bLiechongfuArr和bHangchongfuArr
bHangchongfuArr[line][ a[line][row] ]=false;
bLiechongfuArr[row][ a[line][row] ]=false;



shitanzhi=1;
row++;IsPassCheckLineAndRow(line,row);
}




}
else
{
shitanzhi++;
}
}
}


}


cout<<count<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
ProductAllBsudokuArr(sudokuArr, bsudokuArr);
ProductSudokuJie();




getchar();
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值