题意:给一个没有完成的数独,输出完整结果。数据保证有且只有一个解。
思路:题意明确,思路还是比较好想的,找到每个空的位置,把1到9尝试一遍只要不冲突就填上再往下搜索一直找到解就行了。
卡在两个地方:
1、题目的格式要求。多组输入,输入数据之间有空行,输出的解之间也要有空行。为了解决数据之间的空格,特意搞了一段特盼,为此还WA了两发,后来想起来scanf是自动忽略回车的!所以不需要处理。唉,又是智障错误卡。。。
2、最初选取的搜索对象是每个位置,找到从这个位置开始的第一个空位置,TLE到吐。。。然而怎么都找不出问题,参考了网上的解法,发现都是记录下每个“?”的位置,直接按顺序搜索这些位置就行了,尝试了一下,很快就A了!
关于第二个问题,还是感觉两种方法时间并不会差很大,应该是代码实现问题?这个问题留着,以后再来尝试。
#include<bits/stdc++.h>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;
typedef pair<int,int> P;
P node[90];
int sd[10][10],f=0,cnt;
bool jud(int x,int y,int k){
for(int i=0;i<9;++i){//判断行和列
if(sd[i][y]==k)return false;
if(sd[x][i]==k)return false;
}
int tmpx=(x/3)*3,tmpy=(y/3)*3;
for(int i=tmpx;i<tmpx+3;++i){//判断九宫格
for(int j=tmpy;j<tmpy+3;++j){
if(sd[i][j]==k)return false;
}
}
return true;
}
void dfs(int n){
if(f)return;
if(n==cnt){
f=1;
for(int i=0;i<9;++i){
for(int j=0;j<9;++j){
printf("%d%c",sd[i][j],j==8?'\n':' ');
}
}
return;
}
for(int i=1;i<=9;++i){
if(jud(node[n].first,node[n].second,i)){
sd[node[n].first][node[n].second]=i;
dfs(n+1);
}
if(f)return;//找到结果,退出函数
}
sd[node[n].first][node[n].second]=0;//循环结束也没有解,说明此状态无解,退回0
}
int main(){
char s[5];
int i,j;
while(~scanf("%s",s)){//scanf自动忽略回车,所以不用处理数据之间的空行
cnt=0;
sd[0][0]=(s[0]=='?'?0:s[0]-'0');//处理第一行第一位
for(i=1;i<9;++i){
scanf("%s",s);
sd[0][i]=(s[0]=='?'?0:s[0]-'0');//第一行后面八位
}
for(i=1;i<9;++i){
for(j=0;j<9;++j){
scanf("%s",s);
sd[i][j]=(s[0]=='?'?0:s[0]-'0');//后面八行
}
}
for(int i=0;i<9;++i){//记录没有填的位置
for(int j=0;j<9;++j){
if(!sd[i][j])node[cnt].first=i,node[cnt++].second=j;
}
}
if(f)putchar('\n');//两组解之间有空格
f=0;
dfs(0);
}
}