AcWing 1613. 数独简单版(详解me改成void类型时没输出结果过原因)
原题链接
简单
作者:
記得
,
2021-02-23 23:49:52
,
所有人可见
,
阅读 529
#include<iostream>
#include<cstdio>
using namespace std;
const int N=10;
bool dfs(int x, int y);
char g[N][N];
bool row[N][N], col[N][N], cell[5][5][N];
signed main()
{
for(int i=0;i<9;i++)
{
scanf("%s", g[i]);
for(int j=0;j<9;j++)
if(g[i][j]!='.')
{
int t=g[i][j]-'1';
row[i][t]=col[j][t]=cell[i/3][j/3][t]=true;
}
}
dfs(0, 0);
}
bool dfs(int x, int y)
{
if(y==9) x++, y=0;//如果y到头,置为下一行第一列
if(x==9)
{
for(int i=0;i<9;i++) puts(g[i]);
return true;//这里返回true让下面for里面中间的dfs直接结束,不在回溯,少枚举很多情况
//并且是输出唯一解
}
//MY错误代码 dfs(x, y+1)<-如果当前位是数字,下面就不能循环赋值了。我写成这样,
//该位是数字时,下面有给这一位赋值了,所以枚举不到正确结果不会输出
if(g[x][y]!='.') return dfs(x, y+1);
for(int i=0;i<9;i++)
if(!row[x][i]&&!col[y][i]&&!cell[x/3][y/3][i])
{
g[x][y]=i+'1';
row[x][i]=col[y][i]=cell[x/3][y/3][i]=true;
if(dfs(x, y+1)) return true;//剪枝,dfs返回值是true上面输出了答案,不用再回溯,并且
//这一枝递归直接结束。
g[x][y]='.';
row[x][i]=col[y][i]=cell[x/3][y/3][i]=false;
}
return false;//如果某个方案失败,需要返回false让上面回溯
//不加这个也不会输出结果,因为如果这一枝递归没成功,返回false上面才能回溯
}
//这样写也是对的,只不过没有剪枝,时间复杂度高些
bool dfs(int x, int y)
{
if (y == 9) x ++, y = 0;
if (x == 9)
{
for (int i = 0; i < 9; i ++ ) cout << g[i] << endl;
return true;
}
if (g[x][y] != '.') return dfs(x, y + 1);
for (int i = 0; i < 9; i ++ )
if (!row[x][i] && !col[y][i] && !cell[x / 3][y / 3][i])
{
g[x][y] = i + '1';
row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = true;
dfs(x, y + 1);//不同点
row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = false;
g[x][y] = '.';
}
//没有返回值
}