数独求解算法

本文介绍了一种使用C++实现的数独求解算法,通过数据结构优化存储每个格子的值,并通过一系列检查和排除方法寻找唯一解。算法包括排除已知值、检查3x3宫格、行和列的唯一解,以及进行猜测和回溯。代码包含SudokuData和SudokuParser类,实现了完整的数独求解过程。
摘要由CSDN通过智能技术生成

算法基本思想:

1.数据结构,利用short来存每个格子的值。利用低位的9个bit来表示每个格子的值,如果是待确定的格子,则初始化时将最高位的bit置1,低位9个bit全部置1. 如果是已给出或推算出确定的唯一值,只要置上低位9个bit里对应的1个bit。

2.求解思路

   (1)遍历每个待确定的格子S,

   首先排除S所在9宫其他已确定的值,将那些值对应的bit置0。

   第二,排除S所在列的其他已确定的值,将那些值对应的bit置0。

   第三,排除S所在行的其他已确定的值,将那些值对应的bit置0。

   (2)遍历9个9宫,遍历每个待确定格子,检查该格子的所有可能值,是否有某个可能值只在这个格子里有,而其他8个格子没有的,那么这个格子就是这个值。

   (3)只要在(1)(2)中有某个格子得到唯一解,那么整个遍历结束后需要再一次执行(1)(2),直到没有任何格子的值得到唯一解。这时后有2种状态:

    1就是全部求得解,打印结果,结束。

    2仍然还有待确定的结果,这时就需要猜测值。

          找到第一个待确定格子,将其每个可能值列出来,每个可能值拷贝一份数据,压栈,结束。

   (4) 如果栈不为空,每次pop出一个拷贝,利用(1)(2)(3)来求解。

附代码如下:

SudokuParser.h 

#pragma once

#include <stack>

 

const short unsureValue = (short) 0x81ff; // first bit and last 9 bits set to 1

const short allUnsureValue = 0x1ff; // last 9 bits set to 1

const short convertValue1 = 0x1;

const short convertValue2 = 0x2;

const short convertValue3 = 0x4;

const short convertValue4 = 0x8;

const short convertValue5 = 0x10;

const short convertValue6 = 0x20;

const short convertValue7 = 0x40;

const short convertValue8 = 0x80;

const short convertValue9 = 0x100;

const short convertData[] = {unsureValue, convertValue1, convertValue2, convertValue3, convertValue4,

                       convertValue5, convertValue6, convertValue7, convertValue8, convertValue9};

class SudokuData

{

public:

    SudokuData() {}

    SudokuData(short data[][9]);

    SudokuData& operator=(const SudokuData& val);

    friend class SudokuParser;

private:   

    short mData[9][9];

};

 

class SudokuParser

{

public:

    SudokuParser(const SudokuData& data);

    ~SudokuParser();

 

    // 求解主函数

    void parse();

private:   

    // 返回坐标xy的方格是否是已经有确定了的唯一值。还是有多种可能,确定的话返回1,否则返回0

    int hasConfirm(int x, int y)

    {

        return !(mSudokuData.mData[x][y] & (1 << 16));

    }

 

    // 检查该方格所在的3x3的九格,去掉已经存在的可能值,保留最后剩下的可能值

    void single3x3Check(int x, int y);

 

    // 检查该方格所在列的九格,去掉已经存在的可能值,保留最后剩下的可能值

    void singleRowCheck(int x, int y);

 

    // 检查该方格所在行的九格,去掉已经存在的可能值,保留最后剩下的可能值

    void singleColumnCheck(int x, int y);

 

    // 检查9 3x39宫,遍历每个未确定的格子,检查该格子的所有可能值,是否有某个可能值只在这个格子有,其他8个格子没有的,那么这个格子就是这个值。

    int check3x3UnsureCell();

   

    // 找到第一个未确定的格子,将其所有可能值设置上,并压栈。

    void guessValue();

 

    // 坐标xy的格子是未确定的,将其与其所在九宫里的其他未确定格子比较,确定是否有某个值只在这个格子里有,如果有的话,那么这个格子就是这个值。同时返回1,否则返回0

    int checkIfOnlyOneValue(int startx, int starty, int x, int y, short value);

 

    // 检查是否此格子的值是只有一个唯一值

    int isOnlyOneValue(short value);

   

    // 检查此格子的值是否为0,这表示这格子没有任何可能,一般意味着此数独无解.

    int isNoValue(short value);

 

    // 检查是否所有格子都给出了唯一结果。

    int isAllCleared();

 

    // 对成员变量mSudokuData开始求解

    // return value: -1 means no solution

    //                0 means success

    //                1 means no solution, but it need to guess value and reparse.

    int parseOneData();

 

    // 将内部变量转换成1-9<

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值