数独的C++解法

Posted Ren.Yu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数独的C++解法相关的知识,希望对你有一定的参考价值。

grid.h

 1 #ifndef _GRID_H_
 2 #define _GRID_H_
 3 
 4 #include <set>
 5 #include <cstddef>
 6 
 7 class Grid {
 8 public:
 9     Grid() { for ( int i = 0; i < 9; i++ ) { value_s.insert(i + 1); } }
10 
11     bool set( int value ) {
12         if ( !contain(value) ) { return false; }
13         value_s.clear();
14         value_s.insert(value);
15         return true;
16     }
17 
18     size_t size() { return value_s.size(); }
19     
20     int value() {
21         if ( 1 == size() ) { return *(value_s.begin()); }
22         return -1;
23     }
24 
25     bool remove(int value) {
26         value_s.erase(value);
27         if ( 0 == size() ) { return false; }
28         return true;
29     }
30 
31     int value( int index ) {
32         if ( index >= size() ) { return -1; }
33         std::set<int>::iterator it = value_s.begin();
34         for ( int i = 0; i < index; i++ ) { it ++; }
35         return *it;
36     }
37 private:
38     std::set<int> value_s;
39     
40     bool contain( int value ) { return ( value_s.end() != value_s.find(value) ); }
41 };
42 
43 #endif

sudoku.h

  1 #ifndef _SUDOKU_H_
  2 #define _SUDOKU_H_
  3 
  4 #include "grid.h"
  5 
  6 struct PosVal {
  7     int i;
  8     int j;
  9     int val;
 10     PosVal( int _i, int _j, int _val ) : i(_i), j(_j), val(_val) {}
 11     bool operator < (const PosVal &pos_val) const {
 12         return ( i == pos_val.i ) ? (j < pos_val.j ) : ( i < pos_val.i );
 13     }
 14 };
 15 
 16 struct Result {
 17     int value[9][9];
 18     bool operator < (const Result &result) const {
 19         for ( int i = 0; i < 9; i++ ) {
 20             for ( int j = 0; j < 9; j++ ) {
 21                 if (value[i][j] < result.value[i][j]) { return true; }
 22             }
 23         }
 24         return false;
 25     }
 26 };
 27 
 28 class Sudoku {
 29 public:
 30     Sudoku() {
 31         for ( int i = 0; i < 9; i++ ) {
 32             for ( int j =0; j < 9; j++ ) {
 33                 fixed[i][j] = false;
 34             }
 35         }
 36     }
 37     
 38     bool Init( const std::set<PosVal>& pos_val_s) {
 39         for ( std::set<PosVal>::iterator it = pos_val_s.begin(); it != pos_val_s.end(); it++ ) {
 40             if ( ! set( it->i, it->j, it->val ) ) { return false; }
 41         }
 42         return true;
 43     }
 44     
 45     void calc( std::set<Result>& result_s ) {
 46         if ( !trim() ) { return; }
 47         if ( all_grid_fixed() ) { fill_result( result_s ); return; }
 48         int i, j;
 49         find_unfixed_min_size_grid(i, j);
 50         for ( int loop = 0; loop < size(i, j); loop ++ ) {
 51             Sudoku s( *this );
 52             if ( !s.set(i, j, value(i, j, loop)) ) { return; }
 53             s.calc( result_s );
 54         }
 55     }
 56 private:
 57     Grid grid[9][9];
 58     bool fixed[9][9];
 59     
 60     bool set(int i, int j, int value) {
 61         if ( !grid[i][j].set(value) ) { return false; }
 62         if ( !trim(i, j, value) ) { return false; }
 63         fixed[i][j] = true;
 64         return true;
 65     }
 66     
 67     size_t size(int i, int j) { return grid[i][j].size(); }
 68     
 69     int value(int i, int j ) { return grid[i][j].value(); }
 70     
 71     int value(int i, int j, int index) { return grid[i][j].value(index); }
 72     
 73     bool trim(int ii, int jj, int value) {
 74         for (int j = 0; j < 9; j++) {
 75             if ( j != jj ) { if ( !grid[ii][j].remove(value) ) { return false; } }
 76         }
 77         for (int i = 0; i < 9; i++) {
 78             if ( i != ii ) { if ( !grid[i][jj].remove(value) ) { return false; } }
 79         }
 80         for (int i = (ii/3) * 3; i < (ii/3) * 3 + 3; i++ ) {
 81             for ( int j = (jj/3) * 3; j < (jj/3) * 3 + 3; j++ ) {
 82                 if ( ( i != ii ) || ( j != jj ) ) { if ( !grid[i][j].remove(value) ) { return false; } }
 83             }
 84         }
 85         return true;
 86     }
 87     
 88     bool trim() {
 89         bool has_new_fixed_grid = false;
 90         for (int i = 0; i < 9; i++) {
 91             for (int j = 0; j < 9; j++) {
 92                 if ( !fixed[i][j] && 1 == size(i, j) ) {
 93                     has_new_fixed_grid = true;
 94                     if ( !set(i, j, value(i, j)) ) { return false; }
 95                 }
 96             }
 97         }
 98         if ( has_new_fixed_grid ) { return trim(); }
 99         return true;
100     }
101     
102     void find_unfixed_min_size_grid(int &ii, int &jj) {
103         size_t min_size = 9;
104         for (int i = 0; i < 9; i++ ) {
105             for ( int j = 0; j < 9; j++) {
106                 if ( !fixed[i][j] ) {
107                     if ( size(i, j) < min_size ) { ii = i; jj = j; min_size = size(i, j); }
108                 }
109             }
110         }
111     }
112     
113     bool all_grid_fixed() {
114         for ( int i = 0; i < 9; i++ ) {
115             for ( int j = 0; j < 9; j++ ) {
116                 if ( !fixed[i][j] ) { return false; }
117             }
118         }
119         return true;
120     }
121     
122     void fill_result( std::set<Result>& result_s ) {
123         Result result;
124         for ( int i = 0; i < 9; i++ ) {
125             for ( int j = 0; j < 9; j++ ) {
126                 result.value[i][j] = value(i, j);
127             }
128         }
129         result_s.insert( result );
130     }
131 };
132 
133 #endif

 

main.cpp

 1 #include "sudoku.h"
 2 #include <iostream>
 3 
 4 int main() {
 5     std::set<PosVal> pos_val_s;
 6     pos_val_s.insert(PosVal(0, 0, 8));
 7     pos_val_s.insert(PosVal(1, 2, 3));
 8     pos_val_s.insert(PosVal(1, 3, 6));
 9     pos_val_s.insert(PosVal(2, 1, 7));
10     pos_val_s.insert(PosVal(2, 4, 9));
11     pos_val_s.insert(PosVal(2, 6, 2));
12     pos_val_s.insert(PosVal(3, 1, 5));
13     pos_val_s.insert(PosVal(3, 5, 7));
14     pos_val_s.insert(PosVal(4, 4, 4));
15     pos_val_s.insert(PosVal(4, 5, 5));
16     pos_val_s.insert(PosVal(4, 6, 7));
17     pos_val_s.insert(PosVal(5, 3, 1));
18     pos_val_s.insert(PosVal(5, 7, 3));
19     pos_val_s.insert(PosVal(6, 2, 1));
20     pos_val_s.insert(PosVal(6, 7, 6));
21     pos_val_s.insert(PosVal(6, 8, 8));
22     pos_val_s.insert(PosVal(7, 2, 8));
23     pos_val_s.insert(PosVal(7, 3, 5));
24     pos_val_s.insert(PosVal(7, 7, 1));
25     pos_val_s.insert(PosVal(8, 1, 9));
26     pos_val_s.insert(PosVal(8, 6, 4));
27     
28     Sudoku s;
29     if ( !s.Init( pos_val_s ) ) {
30         return -1;
31     }
32     
33     std::set<Result> result_s;
34     s.calc( result_s );
35     for ( std::set<Result>::iterator it = result_s.begin(); it != result_s.end(); it++ ) {
36         for ( int i = 0; i < 9; i++ ) {
37             for ( int j = 0; j < 9; j++ ) {
38                 std::cout << it->value[i][j] << " ";
39             }
40             std::cout << std::endl;
41         }
42     }
43 }

 

以上是关于数独的C++解法的主要内容,如果未能解决你的问题,请参考以下文章

插播一条 关于数独的解法记录

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

数独算法

数独1--暴力回溯法(时间超)

c++或java 写一个解3阶数独的程序

数独解法小探