#include<bits/stdc++.h>
using namespace std;
#define infile "infile.in"
#define outfile "outfile.out"
#ifdef cin_cout_f
#define cin _____in_____
#define cout _____out_____
ifstream _____in_____(infile);
ofstream _____out_____(outfile);
#else
#ifdef speedup
void spup(){
ios::sync_with_stdio(false);
cin.tie(0);
}
#endif
#endif
#define try_times 81
struct node{
int x,y;
};
int cnt = 81;
unsigned long long ans_counter;
vector<node>nums;//记录可尝试点
vector<vector<int>>img,ans;//img 原始数据 ans 答案
vector<vector<bool>>rest,flag;//rest 原始标记 flag 操作标记
vector<vector<vector<int>>>cases;//cases 每个空缺点可以取值
set<int>lines[15],rows[15],cities[15];
bool cmp(node x,node y){//按可能数从小到大排序
return cases[x.x][x.y].size()<cases[y.x][y.y].size();
}
int city(int i,int j){//计算坐标
return ((i-1)/3)*3+((j-1)/3)+1;
}
void find_cases(){//查找可能数
for(int i = 1;i <= 9;i++){
for(int j = 1;j <= 9;j++){
if(!flag[i][j]){
cases[i][j].clear();
for(int k = 1;k <= 9;k++){
if((!lines[i].count(k))&&(!rows[j].count(k))&&(!cities[city(i,j)].count(k))){
cases[i][j].push_back(k);
}
}
}
}
}
}
void solve(){//对于只有一种可能的点进行解答
for(int i = 1;i <= 9;i++){
for(int j = 1;j <= 9;j++){
if(!flag[i][j]&&cases[i][j].size() == 1){
ans[i][j] = cases[i][j][0];
lines[i].insert(cases[i][j][0]);
rows[j].insert(cases[i][j][0]);
cities[city(i,j)].insert(cases[i][j][0]);
flag[i][j] = 1;
cnt--;
}
}
}
}
bool check(int x,int y,int num){//检查[x][y]上能否填num
return (lines[x].count(num) == 0)&&(rows[y].count(num) == 0)&&(cities[city(x,y)].count(num) == 0);
}
void print(){//彩色打印结果
ans_counter++;
for(int i = 1;i <= 9;i++){
for(int j = 1;j <= 9;j++){
if(!rest[i][j]){
if(ans[i][j]){
printf("\033[38;2;%d;%d;%dm%d \033[0m",0,150,150,ans[i][j]);
}else{
printf("\033[38;2;%d;%d;%dm%d \033[0m",255,0,0,ans[i][j]);
}
}else{
cout<<ans[i][j]<<' ';
}
if(j%3 == 0){
cout<<' ';
}
}
cout<<'\n';
if(i%3 == 0){
cout<<'\n';
}
}
cout<<"-------------------\n";
}
void dfs(int deep){
if(deep >= nums.size()){
print();
return;
}
int x = nums[deep].x,y = nums[deep].y;
for(int i = 0;i < cases[x][y].size();i++){
int t = cases[x][y][i];
if(check(x,y,t)){
ans[x][y] = t;
lines[x].insert(t);
rows[y].insert(t);
cities[city(x,y)].insert(t);
cnt--;
flag[x][y] = 1;
dfs(deep+1);
ans[x][y] = 0;
lines[x].erase(t);
rows[y].erase(t);
cities[city(x,y)].erase(t);
cnt++;
flag[x][y] = 0;
}
}
}
void algo(){
cout<<'\n';
for(int i = 0;i < try_times;i++){
find_cases();
solve();
}
if(cnt <= 0){
print();
}else{
for(int i = 1;i <= 9;i++){
for(int j = 1;j <= 9;j++){
if(!flag[i][j]){
nums.push_back((node){i,j});
}
}
}
sort(nums.begin(),nums.end(),cmp);
dfs(0);
}
if(ans_counter == 0){
printf("\033[38;2;%d;%d;%dm%s \033[0m",255,0,0,"No solution!");
}else{
if(ans_counter == 1){
printf("There is \033[38;2;%d;%d;%dm1\033[0m solution!",0,150,150);
}else{
printf("There are \033[38;2;%d;%d;%dm%lld\033[0m solutions!",0,150,150,ans_counter);
}
}
}
int main(){
img.resize(15,vector<int>(15));
ans.resize(15,vector<int>(15));
flag.resize(15,vector<bool>(15));
rest.resize(15,vector<bool>(15));
cases.resize(15,vector<vector<int>>(15));
for(int i = 1;i <= 9;i++){
for(int j = 1;j <= 9;j++){
int num;
cin>>num;
img[i][j] = ans[i][j] = num;
if(num){
cnt--;
lines[i].insert(num);
rows[j].insert(num);
cities[city(i,j)].insert(num);
rest[i][j] = flag[i][j] = 1;
}
}
}
algo();
system("pause");
return 0;
}
/*
多组解
4 0 0 1 0 9 0 6 0
0 6 0 0 0 0 1 0 0
0 0 7 0 3 0 0 0 0
0 8 0 0 0 0 2 0 0
5 0 0 0 9 0 0 0 3
0 0 9 0 0 0 0 7 0
0 0 0 9 0 0 4 0 0
0 0 4 0 0 0 0 2 0
0 5 0 7 0 3 0 0 1
一组解
0 7 3 0 6 0 0 0 0
1 0 0 0 0 2 0 0 0
8 0 6 1 0 7 0 0 0
0 1 0 0 0 9 0 0 4
5 0 0 0 0 0 0 0 6
7 0 0 8 0 0 0 1 9
0 0 0 9 0 1 8 0 2
0 0 0 2 0 0 0 0 5
0 0 0 0 5 0 3 7 0
一组解(不使用DFS)
0 4 6 0 0 1 7 2 0
5 0 7 2 8 4 1 0 0
1 2 0 6 0 7 8 3 0
9 0 8 5 4 0 3 0 0
4 1 0 0 0 9 0 7 2
2 6 5 0 7 3 9 0 8
0 5 1 0 2 0 6 9 0
7 0 2 0 9 6 4 5 0
6 0 4 0 1 0 2 8 0
*/