当前位置: 代码迷 >> 综合 >> dfs poj2676 数独
  详细解决方案

dfs poj2676 数独

热度:16   发布时间:2024-01-26 03:50:30.0

题目描述:给一个数独,0代表空,解这个数独,有解输出这个解,无解输出原格式

思路:

数独每行每列每块小区域的1-9都是不能重复的
那就设置三个bool来判重
列判重 col[10][10] 行判重 row[10][10] 区域判重 grid[10][10]
列和行判重比较简单,改变前面的那个数字就行,区域判重就要判断输入的那个坐标点是在哪个地方。
每一个点所在的小区域都是3x3形式的,所以我们可以发现行坐标决定的是这个点在哪一行大区域,比如说行号为1,2,3的,他们的区域一定在第一行,行4,5,6,他们的区域一定在第二大行。列坐标一样可以决定这个点在哪个列的大区域,1,2,3列在第一列大区域,4,5,6在第二列大区域。这样就可以计算这个坐标点在哪个区域了。
1,2,3行的属于(1,3)区域,4,5,6行属于(4,6)区域。
可以看作是0+所在列的区域和3+所在列的区域。
列的区域就很好算了,下面直接给公式
i为行坐标,j为列坐标,区域k= ( i - 1 ) / 3 * 3+ ( j - 1 ) / 3 + 1 ;
千万不要k=i / 4 * 3+j / 4 + 1; 因为第7行和第7列会出错。
这个问题解决了那就愉快的dfs了

我用G++跑 ce了,用C++跑ac,咱也不知道为撒

贴代码

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;char s[10][10];     //输入
int map[10][10];         //转化为字符用
bool row[10][10],col[10][10],grid[10][10];bool dfs(int x, int y) {bool flag=false;if ( x==10 ) return true;// 分两种情况,一种是有数字,一种是没数字的情况,这里是有数字if ( map[x][y] ) {if ( y==9 ) flag=dfs(x+1,1);else flag=dfs(x,y+1);if ( flag ) return true;else return false;}//每数字的情况for(int i=1; i<=9; i++ ) {int k=3*((x-1)/3)+(y-1)/3+1;if ( !row[x][i] && !col[y][i] && !grid[k][i] ) {map[x][y]=i;row[x][i]=col[y][i]=grid[k][i]=1;if ( y==9 ) flag=dfs(x+1,1);else flag=dfs(x,y+1);if ( flag ) return true;else {map[x][y]=row[x][i]=col[y][i]=grid[k][i]=0;}}}return false;
}int main()
{int t;cin>>t;while(t--) {memset(row,0,sizeof(row));memset(col,0,sizeof(col));memset(grid,0,sizeof(grid));//处理for(int i=1; i<=9; i++ ) {for(int j=1; j<=9; j++ ) {cin>>s[i][j];map[i][j]=s[i][j]-'0';if ( map[i][j] ) {int k=3*((i-1)/3)+(j-1)/3+1;row[i][map[i][j]]=1;col[j][map[i][j]]=1;grid[k][map[i][j]]=1;}}}dfs(1,1);for(int i=1; i<=9; i++ ) {for(int j=1; j<=9; j++ ) {cout<<map[i][j];}cout<<endl;}}return 0;
}