数独的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 }
时间: 2024-12-20 17:17:04

数独的C++解法的相关文章

求解数独的所有解法,java编程实现

数独是一种考验眼力和逻辑的小游戏,关键在这个"独"字上,横竖不能重复,方块不能重复.今天我给大家介绍一种利用"循环+递归+回溯"的办法来用Java程序替我们完成数独. 先给代码随后讲解: 1 import java.util.HashMap; 2 import java.util.Map; 3 4 public class T2 { 5 public static final int N=3; 6 public static void main(String[] a

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

数独1--暴力回溯法(时间超) 一.心得 可用暴力搜索法(找唯一数单元格)和Dancing Links算法求解 先回顾之前的三篇文章 "算法实践--数独的基本解法",介绍求解数独的基本的暴力搜索法 "跳跃的舞者,舞蹈链(Dancing Links)算法--求解精确覆盖问题",网友huangfeidian介绍的求解数独的舞蹈链(Dancing Links)算法,这篇文章是介绍舞蹈链(Dancing Links)算法的. "算法实践--舞蹈链(Dancing

LeetCode----Sudoku Solver+精确覆盖问题解法(Dancing Links)

BackGround: 做完LeetCode上的数独题目好长时间了,今天将做题时参考的Algorithm X 以及 Dancing Links 整理出来.话说理解算法+写出程序一共用了三天,智商果然余额不足... 介绍: 由于Dancing Links 是为了解决数独问题学习的,那就从数独问题下手,围绕数独问题展开对Algorithm X 和 Dancing Links的介绍,最后将数独问题的解法以及Java源码放出来. 精确覆盖问题: 没错,解数独的问题就是一个解  精确覆盖   问题的过程,

数独程序设计构思

算法实践——数独的基本了解 数独(Sudoku)是一种运用纸.笔进行演算的逻辑游戏.玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字均含1-9,不重复. 每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的. 如下图所示,就是一个数独的题目 关于数独的详细介绍,参看“百度百科——数独” 在经过对数独了解之后,决定用Eclipese平台编程. 数独的基本解法就是利用规则的摒弃法 每一行称为数独的行,每

数独解法小探

数独的游戏要求在一个9X9的格子内填入1~9的数字,使得每一行,每一列,以及九个3X3的子区域内都没有重复的数字. 稍作思索,我写出了第一种解法.从事后查询维基百科1来看,这种方法可以称之为回溯法.思路很简单,依次扫描每一个待填数字的空格: 1. 在第一个空格里面填上“1”,检查这个数字是否合法(其所在的行.列,以及3X3的子区域里不存在重复的数字).如果合法,则前进到第二个格子.否则,在这个格子里继续试2,3,… ,直到合法为止. 2. 在第二个格子里面继续填数字,从“1”开始试起,直到找到一

数独解法

<pre name="code" class="cpp"> <pre name="code" class="cpp">//25...9.4. //4.71.3..6 //8.34.759. //3.8.7..69 //.1.3.24.. //5.49.6.83 //9.6.3.7.8 //.3.6.8.1. //1.2.9.6.4 struct node { node(int r,int c):row(

数独解法(C#)

未完成,回家继续 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Algorithems { class Sudoku_Chain : IAlgorithm { class Blank { public long Possibilies = 0x111111111; public int X;

数独游戏求解:解法适用于任意阶数的数独

0.数独简介 数独(すうどく,Sūdoku)是一种运用纸.笔进行演算的逻辑游戏.以九阶数独为例,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字均含1-9,不重复. 1)4阶(可填数字范围1~4,宫格2阶) 2)9阶(可填数字范围1~9,宫格3阶) 3)16阶(可填数字范围1~16,宫格4阶) *见附录 1.数独的表示 对于N阶数独可以用一个N*N的二维数组表示 1)数独阶数GridRank=N 2)宫格阶数SubGridRank=Sqrt

数独解法c++实现

转自http://blog.csdn.net/qq_31558353/article/details/50615760 用个小样列(据说是世界上最难的数独,10s过) //<pre code_snippet_id="1592833" snippet_file_name="blog_20160301_1_4048211" name="code" class="cpp">#include <iostream>