grid.h

 #ifndef _GRID_H_
#define _GRID_H_ #include <set>
#include <cstddef> class Grid {
public:
Grid() { for ( int i = ; i < ; i++ ) { value_s.insert(i + ); } } bool set( int value ) {
if ( !contain(value) ) { return false; }
value_s.clear();
value_s.insert(value);
return true;
} size_t size() { return value_s.size(); } int value() {
if ( == size() ) { return *(value_s.begin()); }
return -;
} bool remove(int value) {
value_s.erase(value);
if ( == size() ) { return false; }
return true;
} int value( int index ) {
if ( index >= size() ) { return -; }
std::set<int>::iterator it = value_s.begin();
for ( int i = ; i < index; i++ ) { it ++; }
return *it;
}
private:
std::set<int> value_s; bool contain( int value ) { return ( value_s.end() != value_s.find(value) ); }
}; #endif

sudoku.h

 #ifndef _SUDOKU_H_
#define _SUDOKU_H_ #include "grid.h" struct PosVal {
int i;
int j;
int val;
PosVal( int _i, int _j, int _val ) : i(_i), j(_j), val(_val) {}
bool operator < (const PosVal &pos_val) const {
return ( i == pos_val.i ) ? (j < pos_val.j ) : ( i < pos_val.i );
}
}; struct Result {
int value[][];
bool operator < (const Result &result) const {
for ( int i = ; i < ; i++ ) {
for ( int j = ; j < ; j++ ) {
if (value[i][j] < result.value[i][j]) { return true; }
}
}
return false;
}
}; class Sudoku {
public:
Sudoku() {
for ( int i = ; i < ; i++ ) {
for ( int j =; j < ; j++ ) {
fixed[i][j] = false;
}
}
} bool Init( const std::set<PosVal>& pos_val_s) {
for ( std::set<PosVal>::iterator it = pos_val_s.begin(); it != pos_val_s.end(); it++ ) {
if ( ! set( it->i, it->j, it->val ) ) { return false; }
}
return true;
} void calc( std::set<Result>& result_s ) {
if ( !trim() ) { return; }
if ( all_grid_fixed() ) { fill_result( result_s ); return; }
int i, j;
find_unfixed_min_size_grid(i, j);
for ( int loop = ; loop < size(i, j); loop ++ ) {
Sudoku s( *this );
if ( !s.set(i, j, value(i, j, loop)) ) { return; }
s.calc( result_s );
}
}
private:
Grid grid[][];
bool fixed[][]; bool set(int i, int j, int value) {
if ( !grid[i][j].set(value) ) { return false; }
if ( !trim(i, j, value) ) { return false; }
fixed[i][j] = true;
return true;
} size_t size(int i, int j) { return grid[i][j].size(); } int value(int i, int j ) { return grid[i][j].value(); } int value(int i, int j, int index) { return grid[i][j].value(index); } bool trim(int ii, int jj, int value) {
for (int j = ; j < ; j++) {
if ( j != jj ) { if ( !grid[ii][j].remove(value) ) { return false; } }
}
for (int i = ; i < ; i++) {
if ( i != ii ) { if ( !grid[i][jj].remove(value) ) { return false; } }
}
for (int i = (ii/) * ; i < (ii/) * + ; i++ ) {
for ( int j = (jj/) * ; j < (jj/) * + ; j++ ) {
if ( ( i != ii ) || ( j != jj ) ) { if ( !grid[i][j].remove(value) ) { return false; } }
}
}
return true;
} bool trim() {
bool has_new_fixed_grid = false;
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
if ( !fixed[i][j] && == size(i, j) ) {
has_new_fixed_grid = true;
if ( !set(i, j, value(i, j)) ) { return false; }
}
}
}
if ( has_new_fixed_grid ) { return trim(); }
return true;
} void find_unfixed_min_size_grid(int &ii, int &jj) {
size_t min_size = ;
for (int i = ; i < ; i++ ) {
for ( int j = ; j < ; j++) {
if ( !fixed[i][j] ) {
if ( size(i, j) < min_size ) { ii = i; jj = j; min_size = size(i, j); }
}
}
}
} bool all_grid_fixed() {
for ( int i = ; i < ; i++ ) {
for ( int j = ; j < ; j++ ) {
if ( !fixed[i][j] ) { return false; }
}
}
return true;
} void fill_result( std::set<Result>& result_s ) {
Result result;
for ( int i = ; i < ; i++ ) {
for ( int j = ; j < ; j++ ) {
result.value[i][j] = value(i, j);
}
}
result_s.insert( result );
}
}; #endif

main.cpp

 #include "sudoku.h"
#include <iostream> int main() {
std::set<PosVal> pos_val_s;
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , ));
pos_val_s.insert(PosVal(, , )); Sudoku s;
if ( !s.Init( pos_val_s ) ) {
return -;
} std::set<Result> result_s;
s.calc( result_s );
for ( std::set<Result>::iterator it = result_s.begin(); it != result_s.end(); it++ ) {
for ( int i = ; i < ; i++ ) {
for ( int j = ; j < ; j++ ) {
std::cout << it->value[i][j] << " ";
}
std::cout << std::endl;
}
}
}

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

  1. 算法实践——舞蹈链(Dancing Links)算法求解数独

    在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...

  2. 创建随机的9x9数独游戏终盘并打印

    创建随机的9x9数独游戏终盘并打印 项目github地址 1. 项目相关要求 1.1 要求 利用程序随机构造出N个已解答的9x9数独棋盘 . 输入 数独棋盘题目个数N(0<N<=10000 ...

  3. 转载 - 算法实践——舞蹈链(Dancing Links)算法求解数独

    出处:http://www.cnblogs.com/grenet/p/3163550.html 在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dan ...

  4. Leetcode 笔记 36 - Sudoku Solver

    题目链接:Sudoku Solver | LeetCode OJ Write a program to solve a Sudoku puzzle by filling the empty cells ...

  5. 算法练习LeetCode初级算法之数组

    删除数组中的重复项 官方解答: 旋转数组 存在重复元素 只出现一次的数     官方解答:  同一个字符进行两次异或运算就会回到原来的值 两个数组的交集 II import java.util.Arr ...

  6. 36、有效的数独 | 算法(leetode,附思维导图 + 全部解法)300题

    零 标题:算法(leetode,附思维导图 + 全部解法)300题之(36)有效的数独 前言 1)码农三少 ,一个致力于 编写极简.但齐全题解(算法) 的博主. 2)文末附赠 价值上百美刀 资料. 一 ...

  7. [LeetCode] Sudoku Solver 求解数独

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  8. [LeetCode] Valid Sudoku 验证数独

    Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...

  9. LeetCode:Valid Sudoku,Sudoku Solver(数独游戏)

    Valid Sudoku Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku bo ...

随机推荐

  1. 搭建maven+spring+mybatis工程

    一.maven 命令搭建web项目 可以参考我之前的一篇博文maven快速入门 1.搭建web工程 mvn archetype:generate -DgroupId=com.yuanmeng.spri ...

  2. IOS 横屏中添加UIImagePickerController获取系统图片

    今天写ipad的项目,然后需要调用系统相册选择图片,然后用了UIImagePickerController ,崩溃了,后来查了一下,UIImagePickerController只支持竖屏,但是... ...

  3. DHCP Option 60 的理解

    原文地址: http://blog.163.com/chenqioulin_1983/blog/static/83216232010109104430251/   首先还是看看RFC咋说的吧.DHCP ...

  4. C#/Access-数据库获取自动编号的最大值

    //conStrSQL你改成你的access,我这里用的SQL2005string conStrSQL = "Data Source=xx.xx.xx.xx;Initial Catalog= ...

  5. CMake 命令行设定编译环境

    笔者电脑安装了两个版本的VS(VS2012  和 VS2010),在使用CMake编译的时候,如果只在对应目录的命令行输入 "cmake .." 则系统会自动选择使用新版本(VS2 ...

  6. EXE文件结构及读取方法

    一.EXE文件概念 EXE File英文全名executable file ,译作可运行文件,可移植可运行 (PE) 文件格式的文件,它能够载入到内存中,并由操作系统载入程序运行.是可在操作系统存储空 ...

  7. Git链接到自己的Github(2)进阶使用

    接着上一篇的,从github clone下代码. 1.先查看当前开发分支 $ cat .git/HEAD ref: refs/heads/master 这里的master是默认分支. 2.查看当前状态 ...

  8. HDU 4259 - Double Dealing(求循环节)

    首先将扑克牌进行一次置换,然后分解出所有的循环节,所有循环节的扑克牌个数的最小公倍数即为答案 #include <stdio.h> #include <string.h> #i ...

  9. Eclipse 常用快捷键与使用技巧总结

    一.实用类快捷键 1 常用熟悉的快捷键 CTRL+C(复制).CTRL+X(剪切).CTRL+Z(撤销).CTRL+F(查找).CTRL+H(搜索文件或字符串).CTRL+/(双斜杠注释).ALT+/ ...

  10. iOS 开发中你是否遇到这些经验问题(一)

    前言 小伙伴们在开发中难免会遇到问题, 你是如何解决问题的?不妨也分享给大家!如果此文章其中的任何一条问题对大家有帮助,那么它的存在是有意义的! 反正不管怎样遇到问题就要去解决问题, 在解决问题的同时 ...