hdu - 1426 数独(dfs)

本文探讨了使用深度优先搜索(DFS)算法解决数独问题的方法,详细介绍了如何将数独状态转化为搜索树的节点,以及DFS算法的实现细节。通过具体的代码示例,展示了如何判断数独状态的有效性,递归地寻找解决方案,直至找到符合规则的数独填充方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搜索树的概念
将搜索过程中每一步的状态变成树的一个接点;
根节点为搜索树的初始状态;
搜索便是不断扩展这棵树,直至找到目标状态位置;
搜索算法的优化和改正便在于如何拓展搜索树的节点;

解题第一步:如何将状态转化为树中的结点,并构造搜索树;

dfs:对于一个合法的状态A,对于其所有的子状态(搜索树的儿子结点),选择一种进行搜索,递归这一过程,直至到达叶子节点或目前状态不合法,则回溯至父亲节点,对另一种子状态进行搜索。
伪代码:
void dfs(状态A){
    if(A不合法)return ;
    if(A为目标状态)输出;
    if(A不为目标状态)dfs(A+?)//递归调用
}

就是关于dfs有个很关键的地方就是return的处理,要严谨,对于递归的理解有很好的帮助,要找对关键点,防止出现比较恶心的错误,会心态炸的;

这道题首先要理解数独的概念,剩下的就是通过dfs寻找符合条件的数。知道最终找到答案;这道题还有一点关键之处在于对输入输出的处理;是联系dfs的好题;

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define e exp(1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
#define INF 0x3f3f3f3f
#define inf -2100000000
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 100 + 10;
const double EPS = 1e-10;
const ll p = 1e7+9;
const ll mod = 1e9+7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
typedef pair<int, int>P;
P node[90];
int f = 0,cnt;
char m[10][10];
bool jud(int x, int y, int k){
	for(int i = 0; i < 9; i++){
		if(m[i][y] == k+'0')return false;
		if(m[x][i] == k+'0')return false;
	}
	int tmpx = (x/3)*3;
	int tmpy = (y/3)*3;
	for(int i = tmpx; i < tmpx + 3; i++){
		for(int j = tmpy; j < tmpy + 3; j++){
			if(m[i][j] == k + '0') return false;
		}
	}
	return true;
}
void dfs(int n){
	if(f)return ;
	if(n == cnt){
		f = 1;
		for(int i=0;i<9;++i){
	        cout<<m[i][0];
	        for(int j=1;j<9;++j){
	            cout<<' '<<m[i][j];
	        }
	        cout<<endl;
	    }
		return ;
	}
	for(int i = 1; i<= 9; i++){
		if(jud(node[n].first, node[n].second,i)){
			m[node[n].first][node[n].second] = i + '0';
			dfs(n+1);
		}
		if(f) return ;
	}
	m[node[n].first][node[n].second] = 0 + '0';
}

int main(){
	int i,j;
	while(1){
		cnt = 0;
		for(int i = 0; i < 9; i++){
			for(int j = 0; j < 9; j++){
				if(!(cin>>m[i][j]))exit(0);
				if(m[i][j] == '?'){
					node[cnt].first = i,node[cnt++].second = j;
					continue;
				}
			}
		}
		if(f) cout << endl;
		f = 0;
		dfs(0);
	}
	return 0;
}

方法二代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define e exp(1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
#define INF 0x3f3f3f3f
#define inf -2100000000
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 100 + 10;
const double EPS = 1e-10;
const ll p = 1e7+9;
const ll mod = 1e9+7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
typedef pair<int, int>P;
P node[90];
int cnt;
char m[10][10];
bool jud(int x, int y, int k){
	for(int i = 0; i < 9; i++){
		if(m[i][y] == k+'0')return false;
		if(m[x][i] == k+'0')return false;
	}
	int tmpx = (x/3)*3;
	int tmpy = (y/3)*3;
	for(int i = tmpx; i < tmpx + 3; i++){
		for(int j = tmpy; j < tmpy + 3; j++){
			if(m[i][j] == k + '0') return false;
		}
	}
	return true;
}
bool dfs(int n){
	if(n == cnt)return true;	
	for(int i = 1; i<= 9; i++){
		if(jud(node[n].first, node[n].second,i)){
			m[node[n].first][node[n].second] = i + '0';
			if(dfs(n+1))return true;
			m[node[n].first][node[n].second] = '?';
		}
	}
	return false;
}
void output(){
	for(int i=0;i<9;++i){
	    cout<<m[i][0];
	    for(int j=1;j<9;++j){
	        cout<<' '<<m[i][j];
	    }
	    cout<<endl;
	}
	return ;
}
int main(){
	int i,j;
	int f = 0;
	while(1){
		cnt = 0;
		for(int i = 0; i < 9; i++){
			for(int j = 0; j < 9; j++){
				if(!(cin>>m[i][j]))exit(0);
				if(m[i][j] == '?'){
					node[cnt].first = i,node[cnt++].second = j;
					continue;
				}
			}
		}
		dfs(0);
		if(f++)cout << endl;
		output();
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值