题意:给一个没有完成的数独,输出完整结果。数据保证有且只有一个解。
思路:题意明确,思路还是比较好想的,找到每个空的位置,把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); } }