C++算法:解数独------条件递归

leetcode相关C++算法解答: https://github.com/Nereus-Minos/C_plus_plus-leetcode

题目:

编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

方法一:递归(不成功就返回到前一个添值的地方):

首先提取当前有的元素,放在三个vector<map<int,int>>,然后在使用普通递归的方法找出答案,solve(board, row, col, sub, 0, 0, flag); //必须立一个flag,因为当递归到最后,还需要返回到上一次,而之后的代码还原了board,所以需要判断是否需要还原!!!

代码:

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        //首先提取当前有的元素,放在三个vector<map<int,int>>
        vector<map<int,int>> row(9), col(9), sub(9);
        
        rowColSub(board, row, col, sub);
 
        int flag = 0;
        //然后在使用普通递归的方法找出答案
        solve(board, row, col, sub, 0, 0, flag); //必须立一个flag,因为当递归到最后,还需要返回到上一次,而之后的代码还原了board,所以需要判断是否需要还原!!!
        
    }

private:
    void rowColSub(vector<vector<char>>& board, vector<map<int,int>>& row, vector<map<int,int>>& col, vector<map<int,int>>& sub){
        
        for(int i =0; i<9; i++)
            for(int j=0; j<9;j++)
            {
                row[i][board[i][j]] = 1; 
                col[j][board[i][j]] = 1;  
                sub[(i/3)*3 + j/3][board[i][j]] = 1; 
            }
    }
    
    void solve( vector<vector<char>>& temp, vector<map<int,int>>& row, vector<map<int,int>>& col, vector<map<int,int>>& sub, int i, int j, int& flag){
       if(flag == 1)
           return ;
        
        if(j == 9)
        {
            j = 0;
            i++;
        }
        if(i == 9)  //已经解数独了
        {
            flag = 1;
            return ;
        }
        
        while(temp[i][j] != '.')  //确保每次递归回来的i和j是添加值的位置
        {
            j++;
            if(j == 9)
            {
                j = 0;
                i++;
            }
            if(i == 9)  //已经解数独了
            {
                flag = 1;
                return ;
            }
        }
        
        for(int k = 1; k <= 9; k++)
        {
            if(row[i].find(k+48) != row[i].end())
                continue;
            if(col[j].find(k+48) != col[j].end())
                continue;
            if(sub[(i/3)*3 + j/3].find(k+48) != sub[(i/3)*3 + j/3].end())
                continue;
            else
            {
                temp[i][j] = k+48;
                row[i][temp[i][j]] = 1; 
                col[j][temp[i][j]] = 1;  
                sub[(i/3)*3 + j/3][temp[i][j]] = 1; 
                
                solve(temp, row, col, sub, i, j+1, flag);   //递归
               
                if(flag == 1)  //判断是否需要还原
                    return ;
                
                row[i].erase(temp[i][j]); 
                col[j].erase(temp[i][j]);  
                sub[(i/3)*3 + j/3].erase(temp[i][j]); 
                temp[i][j] = '.';
            }
        }
        
        //没找到回到上一次添值的位置重新开始,所以要使用递归
        return ;
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值