数独
传送门
其实这题还是比较水的。(主要是写代码的时候以为枚举判断能够过(就写了300+行),最后还T了。)
只要加三个判断数组vis1 , vis2 ,vis 3 , 分别判断该格子的行、列、宫内的数字有哪些被用过。加上无脑搜索就A了。
有个小坑:本题的输出要放在DFS内,不然搜索回溯后,建好的新图就被清空了。
AC代码:
#include<cstdio>
#include<cstdlib>
using namespace std;
int dt[10][10],vis1[10][10],vis2[10][10],vis3[10][10];
inline int read()
{
char kr=0;
char ls;
for(;ls>'9'||ls<'0';kr=ls,ls=getchar());
int xs=0;
for(;ls>='0'&&ls<='9';ls=getchar())
{
xs=xs*10+ls-48;
}
if(kr=='-') xs=0-xs;
return xs;
}
inline void print()
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
printf("%d ",dt[i][j]);
printf("\n");
}
exit(0);//结束程序
}
inline void dfs(int x,int y)
{
if(x==9&&y==10) print();//打印输出
if(y==10)
{
x+=1,y=1;
}//换行
if(dt[x][y]==0)
{ int tp=0;//特判
for(int j=1;j<=9;j++)
{
int tp1=((x-1)/3)*3,tp2=(y-1)/3,ttp=tp1+tp2;//ttp为第几组
if(vis1[x][j]==0&&vis2[y][j]==0&&vis3[ttp][j]==0)
{
vis1[x][j]=vis2[y][j]=1;
dt[x][y]=j;
vis3[ttp][j]=1;
tp=1;
dfs(x,y+1);
vis1[x][j]=vis2[y][j]=0;dt[x][y]=0;vis3[ttp][j]=0;
}
}
if(tp==0) return;//判断,如果不可行,回溯
}
else dfs(x,y+1);
}
int main()
{
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
{
dt[i][j]=read();
vis1[i][dt[i][j]]=1;vis2[j][dt[i][j]]=1;
vis3[((i-1)/3)*3+(j-1)/3][dt[i][j]]=1;//巧妙的记录一个宫内的数字
}
dfs(1,1);
return 0;
}