C++解数独

#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

*/
posted @ 2024-12-29 12:41  Gavinbeta  阅读(0)  评论(0编辑  收藏  举报