1. 程式人生 > >37.數獨求解

37.數獨求解

Sudoku Solver

問題描述:

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character ‘.’.

You may assume that there will be only one unique solution.
問題
A sudoku puzzle…
解
…and its solution numbers marked in red.

知識補充:

學會靈活使用結構體,結構體也可以作為元素放入棧和佇列中。這樣的話就有多種儲存資料的方法了

char型相互轉化為int型

char c = '1';
int i;
i = (int)c;//強制轉換
i = c-'0';//差值即為所要轉換數字
c = (char)i;//強制轉換
c = char(48+i);//通過差值轉換

參考答案:

class Solution {
        bool check(vector<vector<char>> &board, int i, int j, char val)
        {
            int row = i - i%3, column = j - j%3;
            for
(int x=0; x<9; x++) if(board[x][j] == val) return false; for(int y=0; y<9; y++) if(board[i][y] == val) return false; for(int x=0; x<3; x++) for(int y=0; y<3; y++) if(board[row+x][column+y] == val) return false; return true; } bool
solveSudoku(vector<vector<char>> &board, int i, int j) { if(i==9) return true; if(j==9) return solveSudoku(board, i+1, 0); if(board[i][j] != '.') return solveSudoku(board, i, j+1); for(char c='1'; c<='9'; c++) { if(check(board, i, j, c)) { board[i][j] = c; if(solveSudoku(board, i, j+1)) return true; board[i][j] = '.'; } } return false; } public: void solveSudoku(vector<vector<char>>& board) { solveSudoku(board, 0, 0); } };

效能:

這裡寫圖片描述

參考答案:

class ValidMoves {
private:
    int num_valid;
    int blocked_count[9];

public:
    ValidMoves()
        : num_valid(9), blocked_count {0, 0, 0, 0, 0, 0, 0, 0, 0}
    {}

    inline int valid() const { return num_valid; }

    inline void block(int move) {
        mod(move, 1);
    }

    inline void unblock(int move) {
        mod(move, -1);
    }

    void mod(int move, int d) {
        if(blocked_count[move] == 0) {
            num_valid--;
        }
        blocked_count[move] += d;
        if(blocked_count[move] == 0) {
            num_valid++;
        }
    }

    inline bool isValid(int move) const { return blocked_count[move] == 0; }
};

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        vector<vector<ValidMoves>> validMoves (9, vector<ValidMoves>(9));
        for(int i1=0; i1<9; i1++) {
            for(int i2=0; i2<9; i2++) {
                if(board[i1][i2] != '.') {
                    makeMove(board, validMoves, i1, i2, board[i1][i2] - '1');
                }
            }
        }

        _solveSudoku(board, validMoves);
    }

private:
    void makeMove(vector<vector<char>>& board, vector<vector<ValidMoves>>& validMoves, int i1, int i2, int move) {
        board[i1][i2] = (char)(move + '1');
        modRow(board, validMoves, i1, move, 1);
        modCol(board, validMoves, i2, move, 1);
        modBlock(board, validMoves, i1/3, i2/3, move, 1);
    }

    void unMakeMove(vector<vector<char>>& board, vector<vector<ValidMoves>>& validMoves, int i1, int i2, int move) {
        modBlock(board, validMoves, i1/3, i2/3, move, -1);
        modCol(board, validMoves, i2, move, -1);
        modRow(board, validMoves, i1, move, -1);
        board[i1][i2] = '.';
    }

    inline void modRow(const vector<vector<char>>& board, vector<vector<ValidMoves>>& validMoves, int i1, int move, int d) {
        for(int i2=0; i2<9; i2++) {
            if(board[i1][i2] != '.') {
                continue;
            }
            validMoves[i1][i2].mod(move, d);
        }
    }

    inline void modCol(const vector<vector<char>>& board, vector<vector<ValidMoves>>& validMoves, int i2, int move, int d) {
        for(int i1=0; i1<9; i1++) {
            if(board[i1][i2] != '.') {
                continue;
            }
            validMoves[i1][i2].mod(move, d);
        }
    }

    inline void modBlock(const vector<vector<char>>& board, vector<vector<ValidMoves>>& validMoves, int bi1, int bi2, int move, int d) {
        for(int i1=0; i1<3; i1++) {
            for(int i2=0; i2<3; i2++) {
                int i1_ = i1 + bi1*3, i2_ = i2 + bi2*3;
                if(board[i1_][i2_] != '.') {
                    continue;
                }
                validMoves[i1_][i2_].mod(move, d);
            }
        }
    }

    bool _solveSudoku(vector<vector<char>>& board, vector<vector<ValidMoves>>& validMoves) {
        int most_constrained_count = INT_MAX, most_constrained_i1, most_constrained_i2;        
        for(int i1=0; i1<9; i1++) {
            for(int i2=0; i2<9; i2++) {
                if(board[i1][i2] == '.' && validMoves[i1][i2].valid() < most_constrained_count) {
                    most_constrained_count = validMoves[i1][i2].valid();
                    most_constrained_i1 = i1;
                    most_constrained_i2 = i2;
                }
            }
        }

        if(most_constrained_count == 0) {
            return false;
        }
        if(most_constrained_count == INT_MAX) {
            return true;
        }

        ValidMoves& vm = validMoves[most_constrained_i1][most_constrained_i2];
        for(int move=0; move<9; move++) {
            if(!vm.isValid(move)) {
                continue;
            }

            makeMove(board, validMoves, most_constrained_i1, most_constrained_i2, move);
            if(_solveSudoku(board, validMoves)) {
                return true;
            } else {
                unMakeMove(board, validMoves, most_constrained_i1, most_constrained_i2, move);
            }
        }

        return false;
    }
};

這裡寫圖片描述

相關推薦

37.求解

Sudoku Solver 問題描述: Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by the char

Leetcode #37. Sudoku Solver 求解 結題報告

1 解題報告 做法就只能是暴力的回溯了。。 方法是回溯,用各個標誌位來標誌是否存在衝突 如果數字原來就有了,那麼就跳過處理 因為答案只有一個,所以一旦找到,就要立馬跳出遞迴(如果你用的是棧實現的回溯可能會好處理些) 總之就是仔細些。。。我一次寫過的,而

求解演算法(回溯法和唯一解法)java實現

數獨(すうどく,Sudoku)是一種運用紙、筆進行演算的邏輯遊戲。玩家需要根據9×9盤面上的已知數字,推理出所有剩餘空格的數字,並滿足每一行、每一列、每一個粗線宮內的數字均含1-9,不重複。     注:數獨的各種知識和解決思路請 參考http://www.llang

求解(c語言以及python)

/* ============================================================================ Name : sudoku.c Author : Joey Version

C# 求解演算法。

前言        數獨是一種有趣的智力遊戲,但是部分高難度數獨在求解過程中經常出現大量單元格有多個候選數字可以填入,不得不嘗試填寫某個數字然後繼續推導的方法。不幸的是這種方法經常出現填到一半才發現有單元格無數可填,說明之前就有單元格填錯了把後面的路堵死了。這時就需要悔

軟件工程第一次作業——求解與生成

result pos pre 出了 void 進入 table turn ges 代碼的GitHub地址:https://github.com/Liu-SD/sudoku personal software process stages 預估耗時 實際耗時 計劃

36. Valid Sudoku/37. Sudoku Solver - 問題-- backtracking 經典

題意: 經典的遞迴題, 要求:除了要求 橫豎都填滿 1~9外, 每個3*3也都要求滿足 1~9  36. 陣列可以部分填充, 問是否一個有效的 sudoku.  寫了個好燒腦的 四重迴圈來check 3*3 的部分。  重點在於 用陣列作為hash 。 然後對於 che

終局生成與求解(1)

專案Github地址 https://github.com/Tim-xiaofan/sudoku.git 準備與思考 Visual Studio GitHub程式碼託管配置 廖雪峰的網站有通俗易懂的Git教程 數獨問題 命令列引數的傳遞 (1)控制終

遞迴求解(C語言)

遞迴求解數獨(C語言) 本程式採用c語言編寫,作用是獲得一個數獨的解。 經測試,計算普通數獨時間花費不大於0.02秒。 計算“世界最難數獨”時間花費約為0.05秒。 計算效率中等,有待提高。 程式核心函式為place(),作用為遞迴設定下一個位置的值。

C語言遊戲求解

數獨遊戲的解法: 先將數獨分為九個格子,用一個數組將每個小九宮格的候選數存放下來,將候選數挨個放進數獨裡的空位,如果這一行和這一列都沒有這個數字,繼續放入下一個,如果不能放入的話就回到上一步繼續嘗試,直到成功求出數獨的解為止; 比如這個數獨第一個九宮格的候選數就有1,

徐鬆亮演算法教學-基於C語言的(九宮格)求解(含多解和解數統計)

目錄 一,前言 電腦系統 編譯器 程式語言 流程 演示 一,前言 數獨,說實話我玩過,且並不是很喜歡玩,覺得無聊也太浪費時間,當然玩的水平也不咋樣。 但是我為什麼又寫這篇文章又編寫程式碼的去做呢? 因

2924 挑戰

head ret dia small com turn 智力 運行 lac 2924 數獨挑戰 時間限制: 1 s 空間限制: 1000 KB 題目等級 : 鉆石 Diamond 題解 查看運行結果

codevs 2924 挑戰 x(三種做法+超詳細註釋~)

是否 初始化 cst next using 最大 pos 描述 name 2924 數獨挑戰 時間限制: 1 s 空間限制: 1000 KB 題目等級 : 鉆石 Diamond

dfs

turn print stream images spa namespace () cst n) @_@ 題目: (⊙v⊙)嗯,代碼: 1 #include<iostream> 2 #include<cstdio> 3 usin

dfs(0634-

urn 是把 image main dfs搜索 true 流行 搜索 etc 問題描述 數獨是非常流行的益智遊戲,把一個9x9的九宮格分成9個小的3x3的小九宮,如下圖所示。在這個九宮格上,每個小格子可以填的數字為1,2,3,...,9。初始時,某些格子已經填好數字,剩余

NYOJ 722

width mod cst tac oid ear nyist ios sam 這個之前也做過,只是就是,求出一種解法之後就退出了 能夠非常方便的改成找出全部解的形式 時間限制:1000 ms | 內存限制:65535 KB

Vijos 驗證

pac () getchar() fine false print blog 空白 -h 背景 XX學校風靡一款智力遊戲,也就是數獨(九宮格),先給你一個數獨,並需要你驗證是否符合規則。 描述 具體規則如下:每一行都用到1,2,3,4,5,6,7,8,9,位置不限,每

【NOIP2009】靶形

ios pen printf sub void 數獨 -s ctime pac P1687 - 【NOIP2009】靶形數獨 Description 小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他們想用數獨來一比高低。但普通的數獨對他

[NOIP2009] 靶形

tar 學生 個數 推理 display 數獨遊戲 times 分數 一個空格 [NOIP2009] 靶形數獨 傳送門 題目 小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他們想用數獨來一比高低。但普通的數獨對他們來說都過於簡單了,於是

[NOIP2009]靶形 題解

queue default 白色 isp 利用 要求 noi pan 怎麽辦 407. [NOIP2009] 靶形數獨 時間限制:5 s 內存限制:128 MB 【問題描述】 小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他們想用數獨來一比高