首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用C++解决数独问题(附代码)

用C++解决数独问题(附代码)

作者头像
用户11952558
发布2026-01-09 14:05:57
发布2026-01-09 14:05:57
1540
举报

下面,我们将使用DFS(深度优先搜索)回溯算法剪枝将你小学时的“拦路虎”——数独斩落马下。

前言

数独是一种经典的数字逻辑游戏,它不仅能够锻炼思维能力,还是学习算法设计的绝佳案例。

数独规则:由9x9个空格组成,分为9个3x3的小方格。

每一行、每一列和每个3x3的小方格中,数字1到9只能出现一次

只能使用数字1到9。

算法基础概念

1. DFS(深度优先搜索)

DFS 是一种用于遍历或搜索树或图的算法。它的核心思想是"一条路走到黑":

  • 从根节点开始,沿着某条路径尽可能深地搜索
  • 当到达叶子节点或无法继续时,回溯到上一个分叉点
  • 选择另一条路径继续搜索

在数独中的应用:将每个空位看作决策点,先地尝试所有可能的数字。

2. 回溯算法

回溯算法 是DFS的一种特定形式,主要用于解决约束满足问题:

  • 系统性搜索:尝试所有可能的候选解
  • 剪枝:在发现当前路径不可能得到解时立即放弃
  • 撤销操作:在回退时恢复状态

在数独中的应用:将每个空位看作决策点,先地尝试所有可能的数字

3. 剪枝

剪枝 是优化搜索过程的关键技术,目的是避免无效的搜索路径:

  • 可行性剪枝:当前选择明显违反约束条件时立即停止
  • 最优性剪枝:在优化问题中,当前路径已不可能优于已知最优解时停止

数据结构设计

代码语言:javascript
复制
int a[10][10];          // 数独棋盘
bool row[10][10];       // 行约束:row[i][k]表示第i行是否有数字k
bool col[10][10];       // 列约束:col[j][k]表示第j列是否有数字k  
bool ge[10][10][10];    // 九宫格约束:ge[x][y][k]表示第(x,y)个九宫格是否有数字k
  • int a[10][10]; 数独棋盘
  • bool row[10][10]; 行约束:row[i][k]表示第i行是否有数字k
  • bool col[10][10]; 列约束:col[j][k]表示第j列是否有数字k
  • bool ge[10][10][10]; 九宫格约束:ge[x][y][k]表示第(x,y)个九宫格是否有数字k

核心算法:带剪枝的回溯

代码语言:javascript
复制
bool dfs(int i, int j) {
    // 边界检查:移动到下一行或下一列
    if (i == 9) {
        j++;
        i = 0;
    }
    if (j == 9) return true;  // 成功填充所有格子
    
    // 剪枝:如果当前格子已有数字,直接跳过
    if (a[i][j]) return dfs(i + 1, j);
    
    // 尝试所有可能的数字
    for (int k = 1; k <= 9; k++) {
        // 重要剪枝:检查数字k是否满足所有约束
        if (row[i][k] || col[j][k] || ge[i/3][j/3][k])
            continue;  // 不满足约束,跳过
        
        // 做出选择
        row[i][k] = col[j][k] = ge[i/3][j/3][k] = true;
        a[i][j] = k;
        
        // 递归深入
        if (dfs(i + 1, j)) {
            return true;  // 找到解
        }
        
        // 回溯:撤销选择
        row[i][k] = col[j][k] = ge[i/3][j/3][k] = false;
        a[i][j] = 0;
    }
    
    return false;  // 当前路径无解
}

边界检察

代码语言:javascript
复制
if (i == 9) 
{
    j++;
    i = 0;
}
if (j == 9) 
return true;
  • 当i=9时,表示当前行已填满,移动到下一行
  • 当j=9时,表示所有格子已填充,成功返回

剪枝:跳过已有数字的格子

代码语言:javascript
复制
if (a[i][j]) 
return dfs(i + 1, j);

如果当前格子已有数字,直接跳过

尝试所有可能的数字

  • 从1到9尝试每个数字
  • 检查数字是否满足约束(行、列、3x3宫格)
  • 如果满足,标记为已使用,填充到格子
  • 递归深入尝试下一个格子
  • 如果递归成功,返回true
  • 如果递归失败,回溯(撤销选择)

完整代码实现

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<algorithm>
#include <cstring>
#include<cmath>
#include<queue>
using namespace std;

int _size;
int a[10][10];//数独
bool row[10][10];//行
bool col[10][10];//列
bool ge[10][10][10];//小方格
int r;


bool dfs(int i, int j)
{
	if (i == 9)
	{
		j++; i = 0;
	}
	if (j == 9)return true;
	if (a[i][j])return dfs(i + 1, j);
	for (int k = 1; k <= 9; k++)
	{
		if (row[i][k] || col[j][k] || ge[i / 3][j / 3][k])continue;
		row[i][k] = col[j][k] = ge[i / 3][j / 3][k] = true;
		a[i][j] = k;
		if (dfs(i + 1, j))
		{
			return true;
		}
		row[i][k] = col[j][k] = ge[i / 3][j / 3][k] = false;
		a[i][j] = 0;
	}
	return false;
}


int main()
{
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			cin >> a[i][j];
			int x = a[i][j];
			if (x) 
			{
				row[i][x] = true;
				col[j][x] = true;
				ge[i / 3][j / 3][x] = true;
			}
		}
	}
	dfs(0, 0);
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

算法分析

时间复杂度

  • 最坏情况:O(9^(n)),其中n为空位数
  • 实际运行:通过剪枝大幅优化,通常能在毫秒级解决标准数独

空间复杂度

  • O(1),使用固定大小的数组

关键优化点

  1. 快速约束检查:通过预处理三个标记数组,将约束检查从O(n)降到O(1)
  2. 智能回溯:在发现冲突时立即回溯,避免无效搜索
  3. 系统搜索顺序:按行优先顺序填充,保证完整性

用例

输入

代码语言:javascript
复制
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9

输出

代码语言:javascript
复制
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9

总结

通过这个数独求解器,我们看到了DFS、回溯和剪枝技术的完美结合。这种"尝试-检查-回溯"的模式在解决许多约束满足问题时都非常有效,如八皇后问题等

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 算法基础概念
    • 1. DFS(深度优先搜索)
    • 2. 回溯算法
    • 3. 剪枝
  • 数据结构设计
  • 核心算法:带剪枝的回溯
  • 完整代码实现
  • 算法分析
    • 时间复杂度
    • 空间复杂度
    • 关键优化点
  • 用例
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档