解数独问题

本文讨论了解数独问题的一种方法,通过将数独看作一个竖向的表格,利用回溯算法寻找唯一解。作者强调了回溯函数的实现和判断函数IsVaild在解题中的关键作用。
摘要由CSDN通过智能技术生成

规则:

数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 '.' 表示。

乍一看解数独和N皇后问题很像,甚至会更难些,但其实我觉得二者是差不多的,在解数独的代码里,会加入一个二维的结构,但是其实我们不必那样想,数独是一个9*9的表格,我们可以将其拆成一条竖下来的线,即第二行接到第一行末尾,第三行接到第二行末尾......

这样一来,整个表格就成了一个竖向的表格,其中每一个格子都有1~9可能性,这与n皇后的每一层就非常相似了。

回溯算法

解数独只有一种正确解法,我们只需要找到即可,不需要结果集来搜集,回溯函数的返回值设置为bool,一旦满足条件(最后一个格子也遍历)即返回,结束函数。

bool backtarcking(vector<vector<char>>& chess)
{
    //两个for循环遍历完即找到结果
    for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
                {
                    if(chess[i][j]!='.')
                    {
                        continue;
                    }
                    else
                    {
                        for(int k='1';k<='9';k++)
                            {
                        if(IsVaild(i,j,k,chess))
                        {
                            chess[i][j]=k;
                            //一旦找到,直接一路回溯
                            if(backtracking(chess))
                            {
                                return true;
                            }
                           
                            continue;
                            
                        }
                            }
                        //当1~9都没有合适的,说明上面错误。
                         //返回错误答案,回溯。
                            chess[i][j]='.';
                        return false;
                    }
                }
        }
    return true;
}

 判断

bool IsVaild(int x,int y,int k,vector<vector<char>>& chess)
{
    for(int i=0;i<chess.size();i++)
    {
        if(chess[i][y]==k)
        {
            return false;
        }
    }
    for(int j=0;j<chess[0].size();j++)
    {
        if(chess[x][j]==k)
        {
            return false;
        }
    }
    //3*3方格内不能重复数字
    for(int ix=(x/3)*3;ix<(x/3)*3+3;ix++)
    {
        for(int iy=(y/3)*3;iy<(y/3)*3+3;iy++)
        {
            if(chess[ix][iy]==k)
            {
                return false;
            }
        }
    }
    return true;
}

整体代码

#include <iostream>
#include <vector>
using namespace std;

class solution
{
private:
bool backtracking(vector<vector<char>>& chess)
{
    for(int i=0;i<chess.size();i++)
    {
        for(int j=0;j<chess[0].size();j++)
        {
            if(chess[i][j]!='.')
            {
                continue;
            }
            else 
            {
                for(char k='1';k<='9';k++)
                {
                    if(IsVaild(i, j, k,chess))
                    {
                        chess[i][j]=k;
                        if(backtracking(chess))
                        {
                            return true;
                        }
                        else 
                        {
                            //chess[i][j]='.';
                            continue;
                        }
                    }
                    else 
                    {
                        continue;
                    }
                }
                chess[i][j]='.';
                return false;
            }
        }
    }
    return true;
}
bool IsVaild(int x,int y,int k,vector<vector<char>> chess)
{
    for(int i=0;i<chess.size();i++)
    {
        if(chess[i][y]==k)
        {
            return false;
        }
    }
    for(int j=0;j<chess[0].size();j++)
    {
        if(chess[x][j]==k)
        {
            return false;
        }
    }
    for(int ix=(x/3)*3;ix<(x/3)*3+3;ix++)
    {
        for(int iy=(y/3)*3;iy<(y/3)*3+3;iy++)
        {
            if(chess[ix][iy]==k)
            {
                return false;
            }
        }
    }
    return true;
}
public:
void results(vector<vector<char>>& chess)
{
    backtracking(chess);   
}
};

int main() {
    std::cout << "Hello World!\n";
    vector<vector<char>> chess={{'5','3','.','.','7','.','.','.','.'},
                                {'6','.','.','1','9','5','.','.','.'},
                                {'.','9','8','.','.','.','.','6','.'},
                                {'8','.','.','.','6','.','.','.','3'},
                                {'4','.','.','8','.','3','.','.','1'},
                                {'7','.','.','.','2','.','.','.','6'},
                                {'.','6','.','.','.','.','2','8','.'},
                                {'.','.','.','4','1','9','.','.','5'},
                                {'.','.','.','.','8','.','.','7','9'},};
    solution so;
    so.results(chess);
    for(auto i:chess)
    {
        for(auto j:i)
        {
            cout<<j<<' ';
        }
        cout<<endl;
    }

}


  • 13
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值