Use STL to implement deep search and wide search-Sudoku example (1)

Source: Internet
Author: User
Use STL to implement deep search and wide search -- Sudoku (Sudoku) Example (1)Previously, we used STL containers to implement simple DFS and BFS algorithms. to check their effectiveness, we chose a game-the sudoku Sudoku to implement a simple (but inefficient) process) to test the two DFS and BFS algorithms. Some friends may not be familiar with this Sudoku, so I will give a brief introduction to the rules of this game. As shown in:

The left side is a typical 3x3 Sudoku question, while the right side is the answer to this question. The rule of Sudoku is very simple. The 3x3 Sudoku is a 9x9 matrix. Each lattice in the matrix can be filled with numbers ranging from 1 to 9. The requirement is that each row cannot contain duplicate numbers, duplicate numbers are not allowed for each column, and the square matrix of 9x9 is further divided into 9 small square arrays with 3x3. duplicate numbers are not allowed for each small square matrix. According to the regular Sudoku rule, each question must have only one answer. However, this rule has nothing to do with our search algorithm. We can ignore whether there are no or multiple solutions to the problem, just search (as described in the previous article, our DFS and BFS algorithms have a template parameter, which can be determined by the user to find only one solution or find all solutions ). Now we start to implement this Sudoku program. The DFS and BFS algorithms mentioned above are generic algorithms. We need to provide two things for different specific problems before the search algorithm can be executed. First, it is a class that represents the problem status. In this example, we need to design a class that represents the problem status of the Data independence. The simplest idea is to use a two-dimensional array to represent a state of the sudoku problem. For the 3x3 Sudoku problem, we use a two-dimensional array of 9x9 to represent the state of the problem, the value of each element in the array is 0-9, where 0 represents a space, and 1-9 represents a fixed number. According to our DFS and BFS algorithm requirements, this class needs to provide two member functions: void nextstep (vector <t1> &) and bool istarget (); the former starts from its own State, returns all possible next states. because the number of possible next states is not fixed, we need to use vector <t1> & to return the results. The last member function is relatively simple, return a bool value to determine whether the status meets the answer conditions. In addition, I want to add Stream Input and stream output functions for this class to read the question and output answer. Therefore, this class is defined as follows: Class sudokustate {public: sudokustate () {} void nextstep (vector <sudokustate> &) const; bool istarget () const; friend ostream & operator <(ostream & OS, const sudokustate & S); friend istream & operator> (istream & is, sudokustate & S); Private: int data _ [sudoku_dims] [sudoku_dims];...}; let's start with a simple bool istarget. This is simple. You only need to check all the elements in the two-dimensional array one by one. If all the elements are not 0, it indicates that all the grids in the square matrix have been filled, and the answer has been completed. Of course, we should have checked in istarget () whether these numbers meet the requirements of the sudoku rule. However, we can () make sure that each number entered meets the rule to ensure this, so we can omit this check in istarget. Istarget () is as follows: bool sudokustate: istarget () const {for (int row = 0; row <sudoku_dims; ++ row) {for (INT Col = 0; col <sudoku_dims; ++ col) {If (Data _ [row] [col] = 0) {return false ;}} return true ;} nextstep () it is the core of the algorithm, so it is relatively complicated, but we can also choose from it. First, I chose to implement a simple algorithm. Of course, its efficiency will be relatively low. I decided to delay the optimization of the algorithm. This simple algorithm is to scan a two-dimensional array that represents the problematic state. When the first space is found, find all available numbers for this space (that is, they are not repeated in the row, column, and small square matrix where the space is located ), each number is an optional status next to the current problematic status. According to the requirements of the DFS and BFS algorithms, we insert all the optional next states into the vector object passed in as parameters and return them to DFS and BFS. Void sudokustate: nextstep (vector <sudokustate> & VS) const {sudokustate newstate; bool POS [sudoku_dims]; for (int row = 0; row <sudoku_dims; ++ row) {for (INT Col = 0; Col <sudoku_dims; ++ col) {If (Data _ [row] [col] = 0) // there is a space, find the possible value {fill_n (Pos, sudoku_dims, true); For (INT I = 0; I <sudoku_dims; ++ I) // exclude the same row and column values {checkvalue (Pos, data _ [I] [col]); checkvalue (Pos, data _ [row] [I]);} int rs = Row-(row % sudoku_rows); // exclude the int cs = col-(COL % sudoku_cols) for the same small square matrix; For (INT I = 0; I <sudoku_rows; ++ I) {for (Int J = 0; j <sudoku_cols; ++ J) {checkvalue (Pos, data _ [RS + I] [Cs + J]) ;}for (INT I = 0; I <sudoku_dims; ++ I) {If (Pos [I]) // find a possible candidate value {newstate = * This; newstate. data _ [row] [col] = I + 1; // enter the candidate value with spaces. push_back (newstate); // as the optional status for the Next Step} return; // process only one space in each step }}} in nextstep (), We define a bool array POS [], which records the numbers in the rows, columns, and small square arrays where spaces are located, only those numbers that are not repeated can be filled with spaces. The function calls another member function checkvalue (), which is used to set the bool value of the existing number in the POs array to false. Because it is short, I put it in the class definition. Class sudokustate {public:... private: static void checkvalue (bool * POs, int I) {if (I! = 0) {pos [I-1] = false ;}}; Stream Input and stream output functions are also very simple, just as you often read from the stream or to the stream output elements in the two-dimensional array, ostream & operator <(ostream & OS, const sudokustate & S) {for (INT I = 0; I <sudoku_dims; ++ I) {for (Int J = 0; j <sudoku_dims; ++ J) {OS <S. data _ [I] [J] <";} OS <Endl ;}return OS ;}istream & operator> (istream & is, sudokustate & S) {int V; For (INT I = 0; I <sudoku_dims; ++ I) {for (Int J = 0; j <sudoku_dims; ++ J) {Is> V; S. Data _ [I] [J] = (V <1 | V> sudoku_dims )? 0: V ;}} return is ;}at this point, all components of the problem state sudokustate are listed. Three constants are defined as follows: const int sudoku_rows = 3; const int sudoku_cols = 3; const int sudoku_dims = sudoku_rows * sudoku_cols; sudoku games can be of different sizes, including 2X2, 3x3, 4x4, 5x5, and 2x3, 3x4, and 4x5, so we use two constants to represent the size of a Sudoku game, so that we can easily use this program to solve other size Sudoku games. The second thing required by DFS and BFS algorithms is a function pointer or function object. It accepts a const T1 & Parameter and returns a bool value, the input parameter is an answer State found by the search algorithm. The function can process it in its own way (We will print it ), then a bool value is returned to indicate whether to continue searching for other answers (we only want to find one answer, so true is returned ). Because our processing method is relatively simple, I will use the traditional function pointer directly. If you are interested in using function objects, I think it is not a problem. Bool printresult (const sudokustate & R) {cout <"solution:/N" <r <Endl; return true;} you see, since our sudokustate class already provides stream output functions, printing is very simple. If you want to find all the answers, you can change the return value of the function to false. We have prepared the two things required by the DFS and BFS algorithms. Now it is time to write the main function. As you think, the main function does not have a few lines. It first reads a Sudoku question from Cin, and then calls DFS or BFs to search for the answer. If yes, it gives all the answers and the total number of answers, there are so many: int main () {sudokustate start; CIN> Start; cout <"problem:/N" <start <Endl; int n = depthfirstsearch (START, & printresult); // int n = breadthfirstsearch (START, & printresult); If (n = 0) {cout <"solution not found! /N ";} else {cout <n <" solution (s) found! /N ";} return 0;} you can see, we can choose to use DFS or BFs, they can find the correct answer. At the same time, because the result processing function printresult returns true, it means to find an answer and stop searching. You will find that for most Sudoku problems, DFS is usually faster than BFs. This only shows that the average efficiency of DFS is better than that of BFS for the specific problem of Data independence. If you change printresult to false, it indicates that you need to find all the answers, that is, you need to complete the search of the entire problem status tree. In this way, both DFS and BFS have the same search volume, so their speed will be equal. As mentioned above, this is the first time I have tried this DFS/BFS algorithm. For simplicity, I have adopted the simplest solution without considering the efficiency for the moment. Next time, I will try to improve the efficiency of the solution. Note that it is not the efficiency of the DFS/BFS search algorithm, because they are for general problems, I think there are not many improvements. What I want to improve is the efficiency in the sudokustate: nextstep () member function. If you can make it return the best next state intelligently, that is, to minimize the number of node branches in the next layer of the Status tree, the algorithm efficiency should be effectively improved.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.