Problem Description:
填数独
Presentation Error = =
Input
本题包含多组测试,每组之间由一个空行隔开。每组测试会给你一个 9*9 的矩阵,同一行相邻的两个元素用一个空格分开。其中1-9代表该位置的已经填好的数,问号(?)表示需要你填的数。
Output
对于每组测试,请输出它的解,同一行相邻的两个数用一个空格分开。两组解之间要一个空行。
对于每组测试数据保证它有且只有一个解。
Sample Input
7 1 2 ? 6 ? 3 5 8
? 6 5 2 ? 7 1 ? 4
? ? 8 5 1 3 6 7 2
9 2 4 ? 5 6 ? 3 7
5 ? 6 ? ? ? 2 4 1
1 ? 3 7 2 ? 9 ? 5
? ? 1 9 7 5 4 8 6
6 ? 7 8 3 ? 5 1 9
8 5 9 ? 4 ? ? 2 3
Sample Output
7 1 2 4 6 9 3 5 8
3 6 5 2 8 7 1 9 4
4 9 8 5 1 3 6 7 2
9 2 4 1 5 6 8 3 7
5 7 6 3 9 8 2 4 1
1 8 3 7 2 4 9 6 5
2 3 1 9 7 5 4 8 6
6 4 7 8 3 2 5 1 9
8 5 9 6 4 1 7 2 3
解题思路:
暴力dfs,注意输入输出格式;
代码:
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
int x[9][10],y[9][10],z[3][3][10],n,p,first=0; //x,y,z分别记录每行每列每个小九宫格的数字出现情况,用空间换时间.62ms
char mp[10][10];
vector<pair<int,int> >q;//记录?位置
void dfs(int xn,int yn,int t){
if(p)return;
if(t==n){
p=1;
if(first)putchar('\n'); //PE几次才发现最后一组ans后没有空行= =
for(int i=0;i<9;++i){
for(int j=0;j<9;++j)
printf(j==0?"%c":" %c",mp[i][j]);
putchar('\n');
}
first=1;
return;
}
for(int i=1;i<=9;++i)
if((x[xn][i]||y[yn][i]||z[xn/3][yn/3][i])==0){ //判断该数字可行
if(p)return;
x[xn][i]=1;
y[yn][i]=1;
z[xn/3][yn/3][i]=1;
mp[xn][yn]=i+48;
dfs(q[t+1].first,q[t+1].second,t+1);
x[xn][i]=0;
y[yn][i]=0;
z[xn/3][yn/3][i]=0;
}
}
int main(){
while(~scanf(" %c",&mp[0][0])){ //%c前加个空格可以忽略读入字符前的空格,回车制表符
clr(x,0),clr(y,0),clr(z,0);
p=0;
q.clear();
if(mp[0][0]==63)q.push_back(make_pair(0,0));
else x[0][mp[0][0]-48] =y[0][mp[0][0]-48] =z[0][0][mp[0][0]-48] =1;
for(int i=0;i<9;++i)
for(int j=0;j<9;++j){
if(i==0&&j==0)continue;
scanf(" %c",&mp[i][j]);
if(mp[i][j]==63) q.push_back(make_pair(i,j));
else x[i][mp[i][j]-48] =y[j][mp[i][j]-48] =z[i/3][j/3][mp[i][j]-48] =1;
}
n=q.size();
dfs(q[0].first,q[0].second,0);
}
return 0;
}