#include <stdafx.h>
#include<stdio.h>
#include <cstdlib>
int g_nCount=0;
void print(int array[9][9])//输出可行的解
{
printf("第%d个解:\n",++g_nCount);
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
printf("%d ",array[i][j]);
if((j==2)||(j==5))
printf(" ");
}
printf("\n");
if((i==2)||(i==5))
printf("\n");
}
printf("\n----------------------------------\n");
}
//寻找前一个可填数的位置,找到后修改nRow和nCol的值。
bool PreFillPos(int QuestionArray[9][9],int &nRow,int &nCol)
{
int *pLineArray=(int *)QuestionArray;//二维数组变为一维的
for (int i=nRow*9+nCol-1;i>=0;i--)
{
if(pLineArray[i]==0)
{
nRow=i/9;
nCol=i%9;
return true;
}
}
return false;
}
//寻找下一个可填数的位置,找到后修改nRow和nCol的值。
bool NextFillPos(int QuestionArray[9][9],int &nRow,int &nCol)
{
int *pLineArray=(int *)QuestionArray;
for (int i=nRow*9+nCol+1;i<81;i++)
{
if(pLineArray[i]==0)
{
nRow=i/9;
nCol=i%9;
return true;
}
}
return false;
}
//检测AnswerArray中nRow,nCol中的数在行方向是否合法
bool CheckRow(int AnswerArray[9][9],const int nRow,const int nCol)
{
for (int j=0;j<9;j++)
{
if((AnswerArray[nRow][j]==AnswerArray[nRow][nCol])&&(j!=nCol))
{
return false;
}
}
return true;
}
//检测AnswerArray中nRow,nCol中的数在列方向是否合法
bool CheckCol(int AnswerArray[9][9],const int nRow,const int nCol)
{
for (int i=0;i<9;i++)
{
if((AnswerArray[i][nCol]==AnswerArray[nRow][nCol])&&(i!=nRow))
{
return false;
}
}
return true;
}
//检测AnswerArray中nRow,nCol中的数在所属的九宫格中是否合法
bool CheckArea(int AnswerArray[9][9],const int nRow,const int nCol)
{
int nBeginRow=(nRow/3)*3;
int nBeginCol=(nCol/3)*3;
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
{
if (AnswerArray[nBeginRow+i][nBeginCol+j]==AnswerArray[nRow][nCol]\
&&nBeginRow+i!=nRow\
&&nBeginCol+j!=nCol)
{
return false;
}
}
}
return true;
}
//检测AnswerArray中nRow,nCol中的数在数独中是否合法
bool CheckShudu(int AnswerArray[9][9],const int nRow,const int nCol)
{
return CheckRow(AnswerArray,nRow,nCol)&&CheckCol(AnswerArray,nRow,nCol)&&CheckArea(AnswerArray,nRow,nCol);
}
//解数独,QuestionArray为原数独,主要起参考作用,不可改变。AnswerArray为解答的数组,它保存当前的解答进度。nRow, nCol表示运算到AnswerArray的位置
void JieShudu(int QuestionArray[9][9],int AnswerArray[9][9],int nRow,int nCol)
{
if (!NextFillPos(QuestionArray,nRow,nCol))
{//说明找到,输出来
print(AnswerArray);
}
else
{
for (int i=1;i<=9;i++)
{
AnswerArray[nRow][nCol]=i;
if (CheckShudu(AnswerArray,nRow,nCol))
{
JieShudu(QuestionArray,AnswerArray,nRow,nCol);
}
}
AnswerArray[nRow][nCol]=0;//恢复到最初
}
}
//第一种解法
void Shudu1(int QuestionArray[9][9])
{
int anser[9][9]={0};
memcpy(anser,QuestionArray,sizeof(int[9][9]));
JieShudu(QuestionArray,anser,0,-1);
}
bool FillRightNumber(int AnserArray[9][9],const int nRow,const int nCol)
{
while (true)
{
AnserArray[nRow][nCol]++;
if (AnserArray[nRow][nCol]>9)
return false;
if (CheckShudu(AnserArray,nRow,nCol))
return true;
}
}
bool BackPreRightPos(int QuestionArray[9][9],int AnserArray[9][9],int &nRow,int &nCol)
{
AnserArray[nRow][nCol]=0;//向前找前先把当前位置恢复0
bool bRet=PreFillPos(QuestionArray,nRow,nCol);
if (bRet)
{
if (!FillRightNumber(AnserArray,nRow,nCol))
{
return BackPreRightPos(QuestionArray,AnserArray,nRow,nCol);
}
}
return bRet;
}
//第二种解法
void Shudu2(int QuestionArray[9][9])
{
int anser[9][9]={0};
memcpy(anser,QuestionArray,sizeof(int[9][9]));
int nRow=0;
int nCol=-1;
while(true)
{
if (NextFillPos(QuestionArray,nRow,nCol))
{
if (!FillRightNumber(anser,nRow,nCol))
{//没有合适的数填充就回溯到前一个正确的可填充的位置继续向后找
if(!BackPreRightPos(QuestionArray,anser,nRow,nCol))
return ;
}
}
else
{
print(anser);
//寻找下一组答案
if(!BackPreRightPos(QuestionArray,anser,nRow,nCol))
return;
}
}
}
int main()
{
int a[9][9]=
{
/*{0, 0, 0, 0, 0, 0, 0, 1, 2},
{0, 0, 0, 0, 3, 5, 0, 0, 0},
{0, 0, 0, 6, 0, 0, 0, 7, 0},
{7, 0, 0, 0, 0, 0, 3, 0, 0},
{0, 0, 0, 4, 0, 0, 8, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 2, 0, 0, 0, 0},
{0, 8, 0, 0, 0, 0, 0, 4, 0},
{0, 5, 0, 0, 0, 0, 6, 0, 0} */
{0, 0, 0, 1, 7, 0, 0, 4, 0},
{8, 0, 0, 0, 0, 0, 0, 0, 0},
{7, 1, 9, 0, 0, 8, 0, 3, 0},
{1, 0, 0, 8, 0, 0, 0, 0, 5},
{0, 3, 0, 0, 0, 7, 6, 1, 8},
{9, 0, 0, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 6, 4, 0, 1},
{0, 7, 0, 0, 3, 0, 0, 8, 0},
{0, 0, 8, 4, 1, 0, 7, 2, 3}
};
Shudu1(a);
g_nCount=0;
Shudu2(a);
system("pause");
return 0;
}
#include<stdio.h>
#include <cstdlib>
int g_nCount=0;
void print(int array[9][9])//输出可行的解
{
printf("第%d个解:\n",++g_nCount);
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
printf("%d ",array[i][j]);
if((j==2)||(j==5))
printf(" ");
}
printf("\n");
if((i==2)||(i==5))
printf("\n");
}
printf("\n----------------------------------\n");
}
//寻找前一个可填数的位置,找到后修改nRow和nCol的值。
bool PreFillPos(int QuestionArray[9][9],int &nRow,int &nCol)
{
int *pLineArray=(int *)QuestionArray;//二维数组变为一维的
for (int i=nRow*9+nCol-1;i>=0;i--)
{
if(pLineArray[i]==0)
{
nRow=i/9;
nCol=i%9;
return true;
}
}
return false;
}
//寻找下一个可填数的位置,找到后修改nRow和nCol的值。
bool NextFillPos(int QuestionArray[9][9],int &nRow,int &nCol)
{
int *pLineArray=(int *)QuestionArray;
for (int i=nRow*9+nCol+1;i<81;i++)
{
if(pLineArray[i]==0)
{
nRow=i/9;
nCol=i%9;
return true;
}
}
return false;
}
//检测AnswerArray中nRow,nCol中的数在行方向是否合法
bool CheckRow(int AnswerArray[9][9],const int nRow,const int nCol)
{
for (int j=0;j<9;j++)
{
if((AnswerArray[nRow][j]==AnswerArray[nRow][nCol])&&(j!=nCol))
{
return false;
}
}
return true;
}
//检测AnswerArray中nRow,nCol中的数在列方向是否合法
bool CheckCol(int AnswerArray[9][9],const int nRow,const int nCol)
{
for (int i=0;i<9;i++)
{
if((AnswerArray[i][nCol]==AnswerArray[nRow][nCol])&&(i!=nRow))
{
return false;
}
}
return true;
}
//检测AnswerArray中nRow,nCol中的数在所属的九宫格中是否合法
bool CheckArea(int AnswerArray[9][9],const int nRow,const int nCol)
{
int nBeginRow=(nRow/3)*3;
int nBeginCol=(nCol/3)*3;
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
{
if (AnswerArray[nBeginRow+i][nBeginCol+j]==AnswerArray[nRow][nCol]\
&&nBeginRow+i!=nRow\
&&nBeginCol+j!=nCol)
{
return false;
}
}
}
return true;
}
//检测AnswerArray中nRow,nCol中的数在数独中是否合法
bool CheckShudu(int AnswerArray[9][9],const int nRow,const int nCol)
{
return CheckRow(AnswerArray,nRow,nCol)&&CheckCol(AnswerArray,nRow,nCol)&&CheckArea(AnswerArray,nRow,nCol);
}
//解数独,QuestionArray为原数独,主要起参考作用,不可改变。AnswerArray为解答的数组,它保存当前的解答进度。nRow, nCol表示运算到AnswerArray的位置
void JieShudu(int QuestionArray[9][9],int AnswerArray[9][9],int nRow,int nCol)
{
if (!NextFillPos(QuestionArray,nRow,nCol))
{//说明找到,输出来
print(AnswerArray);
}
else
{
for (int i=1;i<=9;i++)
{
AnswerArray[nRow][nCol]=i;
if (CheckShudu(AnswerArray,nRow,nCol))
{
JieShudu(QuestionArray,AnswerArray,nRow,nCol);
}
}
AnswerArray[nRow][nCol]=0;//恢复到最初
}
}
//第一种解法
void Shudu1(int QuestionArray[9][9])
{
int anser[9][9]={0};
memcpy(anser,QuestionArray,sizeof(int[9][9]));
JieShudu(QuestionArray,anser,0,-1);
}
bool FillRightNumber(int AnserArray[9][9],const int nRow,const int nCol)
{
while (true)
{
AnserArray[nRow][nCol]++;
if (AnserArray[nRow][nCol]>9)
return false;
if (CheckShudu(AnserArray,nRow,nCol))
return true;
}
}
bool BackPreRightPos(int QuestionArray[9][9],int AnserArray[9][9],int &nRow,int &nCol)
{
AnserArray[nRow][nCol]=0;//向前找前先把当前位置恢复0
bool bRet=PreFillPos(QuestionArray,nRow,nCol);
if (bRet)
{
if (!FillRightNumber(AnserArray,nRow,nCol))
{
return BackPreRightPos(QuestionArray,AnserArray,nRow,nCol);
}
}
return bRet;
}
//第二种解法
void Shudu2(int QuestionArray[9][9])
{
int anser[9][9]={0};
memcpy(anser,QuestionArray,sizeof(int[9][9]));
int nRow=0;
int nCol=-1;
while(true)
{
if (NextFillPos(QuestionArray,nRow,nCol))
{
if (!FillRightNumber(anser,nRow,nCol))
{//没有合适的数填充就回溯到前一个正确的可填充的位置继续向后找
if(!BackPreRightPos(QuestionArray,anser,nRow,nCol))
return ;
}
}
else
{
print(anser);
//寻找下一组答案
if(!BackPreRightPos(QuestionArray,anser,nRow,nCol))
return;
}
}
}
int main()
{
int a[9][9]=
{
/*{0, 0, 0, 0, 0, 0, 0, 1, 2},
{0, 0, 0, 0, 3, 5, 0, 0, 0},
{0, 0, 0, 6, 0, 0, 0, 7, 0},
{7, 0, 0, 0, 0, 0, 3, 0, 0},
{0, 0, 0, 4, 0, 0, 8, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 2, 0, 0, 0, 0},
{0, 8, 0, 0, 0, 0, 0, 4, 0},
{0, 5, 0, 0, 0, 0, 6, 0, 0} */
{0, 0, 0, 1, 7, 0, 0, 4, 0},
{8, 0, 0, 0, 0, 0, 0, 0, 0},
{7, 1, 9, 0, 0, 8, 0, 3, 0},
{1, 0, 0, 8, 0, 0, 0, 0, 5},
{0, 3, 0, 0, 0, 7, 6, 1, 8},
{9, 0, 0, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 6, 4, 0, 1},
{0, 7, 0, 0, 3, 0, 0, 8, 0},
{0, 0, 8, 4, 1, 0, 7, 2, 3}
};
Shudu1(a);
g_nCount=0;
Shudu2(a);
system("pause");
return 0;
}