解数独(回溯)

大兔子大兔子 提交于 2020-03-03 22:51:28

在这里插入图片描述
在这里插入图片描述
我觉得这题的思路还是很简单的,回溯法
就是模拟人解数独时的简单想法:

人在解数独的时候要注意每一行、每一列、每一个子数独中哪些数字已经被使用过了;

一行一行的进行填充,填充完一行就到下一行继续填充;

如果一个单元格中不为空,则去下一个单元格;

如果一个单元格为空,我们就看一下这个单元格所属的行、列、子数独中有哪些数字没有使用过,就将未使用过的数字填入单元格,并且记录这个被填入的数字在此单元格所属的行、列、子数独中已经被使用过了;

如果出现因为之前填充空格时选择不佳,导致无法继续填写空格的情况,就逐步擦除之前填入的数字,并将被擦除的数字在所属的行、列、子数独中设置为未使用的状态后,重新选择下一个未使用过的数字进行填充,尝试继续完成填充;

如果已经填充完所有行,即成功解数独。

思路理清后,代码很快就写好了:

class Solution {
public:
	void solveSudoku(vector<vector<char>>& board) {
		for (int i = 0; i < 9; i++)
			for (int j = 0; j < 9; j++)
			{
				if (board[i][j] != '.')
				{
					rows[i][board[i][j] - '0' - 1] = true;
					cols[j][board[i][j] - '0' - 1] = true;
					blocks[i / 3 * 3 + j / 3][board[i][j] - '0' - 1] = true;
				}
			}

		DFS(board, 0, 0);
	}
	//深度遍历,row记录当前要填写的行,col记录当前要填写的列
	void DFS(vector<vector<char>>& board, int row, int col)
	{
		//0-8行都已经填写,解数独完毕
		if (row == 9) {
			finished = true;
			return;
		}
		//不是空白格,不需要填写,继续向后移动
		if (board[row][col] != '.')
		{
			//如果本行已经是最后一列,则继续填写下一行的第一列;否则继续当前行的下一列。
			if (col == 8) DFS(board, row + 1, 0);
			else DFS(board, row, col + 1);
		}
		else//是空白格,按顺序将当前行、列、子数独未使用的数字尝试填入空白格
		{
			for (char number = '1'; number <= '9'; number++)
			{
				if (!rows[row][number - '0' - 1] && !cols[col][number - '0' - 1] && !blocks[row / 3 * 3 + col / 3][number - '0' - 1])
				{
					board[row][col] = number;
					rows[row][number - '0' - 1] = cols[col][number - '0' - 1] = blocks[row / 3 * 3 + col / 3][number - '0' - 1] = true;
					//填写完毕当前空白格,继续填写下一格
					if (col == 8)DFS(board, row + 1, 0);
					else DFS(board, row, col + 1);
					//如果当前尝试填入的数字不能成功解数独(导致后序空白格无法填写),则回溯
					if (!finished)
					{
						//擦除填入的数字,并更新被擦除数字的状态
						board[row][col] = '.';
						rows[row][number - '0' - 1] = cols[col][number - '0' - 1] = blocks[row / 3 * 3 + col / 3][number - '0' - 1] = false;
					}
				}
			}
		}

	}



private:
	bool rows[9][9] = { false };//rows[i][j]为true表示第i+1行的数字j+1已经被使用了
	bool cols[9][9] = { false };//cols[i][j]为true表示第i+1列的数字j+1已经被使用了
	bool blocks[9][9] = { false };//cols[i][j]为true表示第i+1个子数独中数字j+1已经被使用了
	bool finished = false;
};

在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!