数独的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 ...
随机推荐
- ASP.NET线程与异步
什么是线程? 线程简单来说就是一种数据结构,用来管理这个程序的执行状态,其中包括 1.线程核心对象->寄存器的状态 2.线程环境块,是一块用户模式下的内存,包含线程的异常处理链的头部.线程的局部 ...
- centos7 挂载ntfs移动硬盘
第一步:下载安装rpmforge ,下载地址 http://pkgs.repoforge.org/rpmforge-release/ 安装 rpm -ivh rpmforge-release-0.5 ...
- 网页标签图片如何保存&下载?
最简单的方法就是鼠标右键,查看网页源代码,ctrl+f输入favicon.ico,一般网站都是这个
- 完全分布式Hadoop2.3安装与配置
一.Hadoop基本介绍 Hadoop优点 1.高可靠性:Hadoop按位存储和处理数据 2.高扩展性:Hadoop是在计算机集群中完成计算任务,这个集群可以方便的扩展到几千台 3.高效性:Hadoo ...
- 【IBM】使用 CAS 在 Tomcat 中实现单点登录
来源: IBM Developer http://www.ibm.com/developerworks/cn/opensource/os-cn-cas/ 张 涛 (zzhangt@cn.ibm.com ...
- FindWindow使用方法
函数功能:该函数获得一个顶层窗体的句柄,该窗体的类名和窗体名与给定的字符串相匹配.这个函数不查找子窗体.在查找时不区分大写和小写. 函数型:HWND FindWindow(LPCTSTR IpClas ...
- TortoiseGit disconnected: no supported authentication methods available(server sent:publickey)
之前一直用命令行,现在想用图形工具,TortoiseGit,安装后遇到错误 TortoiseGit disconnected: no supported authentication methods ...
- android学习日记08--Paint画笔
Paint 要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布Canvas上,这样才可以显示在手机屏幕上.Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设 ...
- 信号之alarm和pause函数
使用alarm函数可以设置一个计时器,在将来某个指定的时间,该计时器会超时.当计时器超时时,产生SIGALRM信号.如果不忽略或不捕捉此信号,则其默认动作是终止调用该alarm函数的进程. #incl ...
- 文件和目录之symlink和readlink函数
symlink函数创建一个符号链接. #include <unistd.h> int symlink( const char *actualpath, const char *sympat ...