数独的C++解法

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++解法的更多相关文章
- 算法实践——舞蹈链(Dancing Links)算法求解数独
在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...
- 创建随机的9x9数独游戏终盘并打印
创建随机的9x9数独游戏终盘并打印 项目github地址 1. 项目相关要求 1.1 要求 利用程序随机构造出N个已解答的9x9数独棋盘 . 输入 数独棋盘题目个数N(0<N<=10000 ...
- 转载 - 算法实践——舞蹈链(Dancing Links)算法求解数独
出处:http://www.cnblogs.com/grenet/p/3163550.html 在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dan ...
- Leetcode 笔记 36 - Sudoku Solver
题目链接:Sudoku Solver | LeetCode OJ Write a program to solve a Sudoku puzzle by filling the empty cells ...
- 算法练习LeetCode初级算法之数组
删除数组中的重复项 官方解答: 旋转数组 存在重复元素 只出现一次的数 官方解答: 同一个字符进行两次异或运算就会回到原来的值 两个数组的交集 II import java.util.Arr ...
- 36、有效的数独 | 算法(leetode,附思维导图 + 全部解法)300题
零 标题:算法(leetode,附思维导图 + 全部解法)300题之(36)有效的数独 前言 1)码农三少 ,一个致力于 编写极简.但齐全题解(算法) 的博主. 2)文末附赠 价值上百美刀 资料. 一 ...
- [LeetCode] Sudoku Solver 求解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
- [LeetCode] Valid Sudoku 验证数独
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...
- LeetCode:Valid Sudoku,Sudoku Solver(数独游戏)
Valid Sudoku Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku bo ...
随机推荐
- linux shell date格式化配置
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- 【推荐】对 Linux 用户非常有用的 60 个命令(由浅入深)
对 Linux 新手非常有用的 20 个命令 http://www.oschina.net/translate/useful-linux-commands-for-newbies 对 Linux 中级 ...
- WINHTTP的API接口说明。
BOOL WINAPI WinHttpAddRequestHeaders( _In_ HINTERNET hRequest, _In_ LPCWSTR pwszHeaders, _In ...
- 重装系统后QQ聊天记录恢复方法
重装系统后QQ聊天记录恢复方法 近日又一次安装了系统,又一次安装了腾讯的.TM,TM也是安装在之前的文件夹底下,可是聊天记录和之前的自己定义表情都不见了,看来没有自己主动恢复回来. 我这里另一个特殊的 ...
- Java路径操作具体解释
1.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或文件夹在硬盘上真正的路径.(URL和物理路径)比如: C:\xyz\test.txt 代表了test.txt文件的绝对路径.http://w ...
- 如何编写程序设置Android来电铃声
我们在拿到新手机后通常会为其设置来年铃声,那么怎样通过代码来设置Android来电铃声,本文就为大家实例讲解下. 1.如果读到的是音频文件路径,需要先将音乐文件插入到多媒体库. Java代码 //设置 ...
- pomelo 开发环境搭建
开发前提条件: Windows系统,请确保你的Windows系统包括源代码编译工具.Node.js的源代码主要由C++代码和JavaScript代码构成,可是却用gyp工具来做源代码的项目管理,该工 ...
- android EditText输入变化事件详解
editText.addTextChangedListener(new TextWatcher(){ public void afterTextChanged(Editable s) { // ...
- scrollLeft、offsetLeft、clientLeft、clientHeight详解
offsetLeft:Html元素相对于自己的offsetParent元素的位置 scrollLeft:返回和设置当前横向滚动务的坐标值 scrollLeft.offsetLeft.clientLef ...
- mysql中不同事务隔离级别下数据的显示效果--转载
事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...