这个题必须要写一篇博客了……这个题算是做过的最久的一道题吧。想了很长时间,一直没想好怎么做。要保证每一行每一列还有没个格子都不重复,行和列还好说,每个格子不一样不知道怎么做。搜索的话,开始是想几个方向一起搜,但是想想不行,又想一行一列一起搜,想想也不行。想了好久都不知道怎么搜。实在想不出来了,最后了解了一下别人的思路,一行一行的搜……感觉也考虑过……但是就这个没写过了。
下面是原题:(感觉这个代码可以解决所有数独的问题,感觉像是完成了一项大工程一样……)
1 103000509 002109400 000704000 300502006 060000050 700803004 000401000 009205800 804000107
143628579 572139468 986754231 391542786 468917352 725863914 237481695 619275843 854396127
这个题比较关键的地方就在于对数字的标记。即这个数存在过,就在数组中进行标记。对于格子的问题,也可以标记……
解题思路就是从最左上角开始,满足条件DFS(i,j+1),如果j == 8,搜下一行DFS(i+1,j)。一直到i==9,搜索完成。
下面附源代码:
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
using namespacestd;
int hang[9][10]; //用于记录第i行中j数字是否出现过
int lie[10][9]; //用于记录第j列中i数字是否出现过
int ge[9][10]; //用于记录格子中j个数字是否出现过
struct Shudu
{
string a;
}shudu[9];
int flag;
void print()
{
for (int i = 0; i < 9; i++)
{
cout <<shudu[i].a;
cout <<endl;
}
}
void DFS(int m,int n)
{
if (m == 9)
{
flag = 1;
print();
return ;
}
if (flag == 1)
return ;
if (shudu[m].a[n] != '0')
{
if (n == 8)
DFS(m + 1,0);
else
DFS(m,n+1);
}
if (shudu[m].a[n] == '0')
{
for (int t = 1; t <= 9; t++)
{
int k = m / 3 * 3 + n / 3;
if (hang[m][t] != 1 &&lie[t][n] != 1 &&ge[k][t] != 1)
{
hang[m][t] = 1;
lie[t][n] = 1;
ge[k][t] = 1;
shudu[m].a[n] =char(t + 48);
}
else
continue;
if (n == 8)
DFS(m+1,0);
else
DFS(m,n+1);
shudu[m].a[n] = '0';
hang[m][t] = 0;
lie[t][n] = 0;
ge[k][t] = 0;
}
}
}
int main()
{
int n;
scanf("%d",&n);
while (n--)
{
memset(hang,0,sizeof(hang));
memset(lie,0,sizeof(lie));
memset(ge,0,sizeof(ge));
int i,j;
for (i = 0; i < 9; i++)
{
cin >>shudu[i].a;
for (j = 0; j < 9; j++)
{
if (shudu[i].a[j] != '0')
{
hang[i][int(shudu[i].a[j]-'0')] = 1;
lie[int(shudu[i].a[j]-'0')][j] = 1;
int k;
k = i / 3 * 3 + j / 3;
/*
将整个数组分为9个格子。
k = 1 ,i = 0 to 2,j = 0 to 2;
k = 2 ,i = 0 to 2,j = 3 to 5;
k = 3 ,i = 0 to 2,j = 6 to 8;
...........
第k个格子即为k = i / 3 * 3 + j / 3;
*/
ge[k][int(shudu[i].a[j] - '0')] = 1;
}
}
}
// for (i = 0; i < 9; i++)
//{
// for (j = 0; j < 10; j++)
// cout << hang[i][j] << " ";
// cout << endl;
// }
cout <<endl;
flag = 0;
DFS(0,0);
}
return 0;
}
k(格子) i(行数) j(列数)
1 0~2 0~2
2 0~2 3~5
3 0~2 6~8
4 3~5 0~2
5 3~5 3~5
6 3~5 6~8
7 6~8 0~2
8 6~8 3~5
9 6~8 6~8
找关系就行……
还是从这个题中学到了很多。
争取下次标记问题可以做的更好。搜索的思路以及终止条件可以越来越清楚。
这个题对我的帮助还是很大的。