C++实现数独(附带过程)
首先,来到这里的人应该都知道数独是什么。
那么,如果没有c++,你,在面对数独时会怎么做?
1.纯方法
1.摒除法:用数字去找单元内唯一可填空格,称为摒除法,数字可填唯一空格称为摒余解(隐性唯一解)。
就是通过某一个格子所在行与列和宫,确定当前格子上的数:
1 | 3 | 4 | ||||||
5(x) | 5(x) | 5(x) | 5 | |||||
5(x) | 5(x) | 5 | ||||||
5 | 5 | |||||||
根据已知三个“5”,排除一宫8个格子,得到“5”的掘除法
#ifndef SHUDUFA_H
#define SHUDUFA_H//定义头文件
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P; P ji[11];
int kuai[11][11],lie[11][11],hang[11][11],ma[11][11],k,mm[11][11];
inline int d(int pd,int x,int y) {if(pd==1) return x; else return y;}
inline int find(int num)
{int jinum=0;for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) if(ma[i][j]==num) ji[++jinum]=P(i,j);return jinum;
}//find(i)表示寻找数独上所有i数字的坐标并存于ji[i]中。
inline void biao_hui(int p,int x,int y,int val,int howk)
{hang[x][val]=p;lie[y][val]=p;kuai[howk][val]=p;mm[x][y]=1;ma[x][y]=p*val;k+=2*p-1;
}//biao_hui(p,x,y,val,howk)表示将数独第(x,y)个格子填入val且仅当p=1,标记(p=0时为回溯)
inline void does(int i1,int i2,int j1,int j2,int temp[11][11],int num,int howk)
{int sum=0,x,y; for(int i=i1;i<=i2;i++){for(int j=j1;j<=j2;j++){if(temp[i][j]) sum++;else x=i,y=j;}}if(sum==8&&kuai[howk][num]==0) biao_hui(1,x,y,num,howk);//宫内唯一解
}
inline void tian(int shu,int num)
{int temp[11][11];for(int j=1;j<=9;j++) for(int kk=1;kk<=9;kk++) temp[j][kk]=mm[j][kk];//记录那些位置没填,temp与mm此处功能一样。for(int i=1;i<=shu;i++){int x=ji[i].first,y=ji[i].second;for(int j=1;j<=9;j++) temp[x][j]=temp[j][y]=1;}//将数字num用于行列摒除法,再找宫内唯一解。for(int i=1;i<=3;i++){int xr=i*3,xl=xr-2;for(int j=1;j<=3;j++) does(xl,xr,(j-1)*3+1,j*3,temp,num,(i-1)*3+j);//找宫内唯一解并填入(上转does)}
}
inline void does2(int pd)//pd=1为求行内唯一解,pd=2为求列内唯一解
{if(pd==0){for(int i=1;i<=9;i++) tian(find(i),i);return;}for(int i=1;i<=9;i++){queue<int> q;int use[11],bu=0;memset(use,0,sizeof(use)); for(int j=1;j<=9;j++){if(!hang[d(pd,i,j)][d(pd,j,i)]){q.push(d(pd,j,i));use[d(pd,j,i)]=1;bu++;}}for(int j=1;j<=9;j++){if(ma[d(pd,i,j)][d(pd,j,i)]) continue;int num=(d(pd,i,j)-1)/3*3+(d(pd,j,i)-1)/3+1;for(int ki=1;ki<=9;ki++){if(use[ki]){int uu=0;for(int kk=1;kk<=9;kk++){if(use[kk]&&ki!=kk){if(kuai[num][kk]||hang[d(pd,i,j)][kk]||lie[d(pd,j,i)][kk]) uu++;}}if(uu==bu-1&&!kuai[num][ki]&&!hang[d(pd,i,j)][ki]&&!lie[d(pd,j,i)][ki]){bu--;use[ki]=0;biao_hui(1,d(pd,i,j),d(pd,j,i),ki,num);}}}}}
}
#endif
2.余数法:用格位去找唯一可填数字,称为余数法,格位唯一可填数字称为唯余解(Naked Single)。(这简单,不用赘述)
3.直观法:不做任何记号,直接从数独的盘势观察线索,推论答案的方法。蒙圈......
4.候选数法就是删减等位群格位已出现的数字,将剩余可填数字填入空格做为解题线索的参考,可填数字称为候选数(Candidates,或称备选数)。(好恐怖)
2.c++思想:
1.暴力搜索
inline void dfs(int nx,int ny)
{if(ma[nx][ny]) {if(ny==9){if(nx<9) dfs(nx+1,1);else return;}else dfs(nx,ny+1);return;}for(int i=1;i<=9;i++){if(hang[nx][i]||lie[ny][i]||kuai[((nx-1)/3*3+(ny-1)/3+1)][i]) continue;biao_hui(1,nx,ny,i,((nx-1)/3*3+(ny-1)/3+1));if(k==81){print(ma);continue;}if(ny==9){if(nx<9) dfs(nx+1,1);else continue;}else dfs(nx,ny+1);biao_hui(0,nx,ny,i,((nx-1)/3*3+(ny-1)/3+1));}
}
2.使用上述方法
#ifndef SHUDUFA_H
#define SHUDUFA_H
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P; P ji[11];
int kuai[11][11],lie[11][11],hang[11][11],ma[11][11],k,mm[11][11];
inline int d(int pd,int x,int y) {if(pd==1) return x; else return y;}
inline int find(int num)
{int jinum=0;for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) if(ma[i][j]==num) ji[++jinum]=P(i,j);return jinum;
}
inline void biao_hui(int p,int x,int y,int val,int howk)
{hang[x][val]=p;lie[y][val]=p;kuai[howk][val]=p;mm[x][y]=1;ma[x][y]=p*val;k+=2*p-1;
}
inline void does(int i1,int i2,int j1,int j2,int temp[11][11],int num,int howk)
{int sum=0,x,y; for(int i=i1;i<=i2;i++){for(int j=j1;j<=j2;j++){if(temp[i][j]) sum++;else x=i,y=j;}}if(sum==8&&kuai[howk][num]==0) biao_hui(1,x,y,num,howk);
}
inline void tian(int shu,int num)
{int temp[11][11];for(int j=1;j<=9;j++) for(int kk=1;kk<=9;kk++) temp[j][kk]=mm[j][kk];for(int i=1;i<=shu;i++){int x=ji[i].first,y=ji[i].second;for(int j=1;j<=9;j++) temp[x][j]=temp[j][y]=1;}for(int i=1;i<=3;i++){int xr=i*3,xl=xr-2;for(int j=1;j<=3;j++) does(xl,xr,(j-1)*3+1,j*3,temp,num,(i-1)*3+j);}
}
inline void does2(int pd)
{if(pd==0){for(int i=1;i<=9;i++) tian(find(i),i);return;}for(int i=1;i<=9;i++){queue<int> q;int use[11],bu=0;memset(use,0,sizeof(use)); for(int j=1;j<=9;j++){if(!hang[d(pd,i,j)][d(pd,j,i)]){q.push(d(pd,j,i));use[d(pd,j,i)]=1;bu++;}}for(int j=1;j<=9;j++){if(ma[d(pd,i,j)][d(pd,j,i)]) continue;int num=(d(pd,i,j)-1)/3*3+(d(pd,j,i)-1)/3+1;for(int ki=1;ki<=9;ki++){if(use[ki]){int uu=0;for(int kk=1;kk<=9;kk++){if(use[kk]&&ki!=kk){if(kuai[num][kk]||hang[d(pd,i,j)][kk]||lie[d(pd,j,i)][kk]) uu++;}}if(uu==bu-1&&!kuai[num][ki]&&!hang[d(pd,i,j)][ki]&&!lie[d(pd,j,i)][ki]){bu--;use[ki]=0;biao_hui(1,d(pd,i,j),d(pd,j,i),ki,num);}}}}}
}
#endif
3.完整代码:
cpp:
#include"bits/stdc++.h"
#include"shudufa.h"
#include"reawri.h"
using namespace std;
inline void dfs(int nx,int ny)
{if(ma[nx][ny]) {if(ny==9){if(nx<9) dfs(nx+1,1);else return;}else dfs(nx,ny+1);return;}for(int i=1;i<=9;i++){if(hang[nx][i]||lie[ny][i]||kuai[((nx-1)/3*3+(ny-1)/3+1)][i]) continue;biao_hui(1,nx,ny,i,((nx-1)/3*3+(ny-1)/3+1));if(k==81){print(ma);continue;}if(ny==9){if(nx<9) dfs(nx+1,1);else continue;}else dfs(nx,ny+1);biao_hui(0,nx,ny,i,((nx-1)/3*3+(ny-1)/3+1));}
}
inline void work()
{int t=0;string a,b;while(k<81){if(t==0) a="(区域确定式)",b="(横线确定式)";if(t==1) a="(横线确定式)",b="(竖线确定式)";int lastk=k;for(int i=0;i<=t;i++) does2(t);if(lastk==k){print(ma);cout<<("仅有"+a+"法不可行\n加入法"+b+"\n");t++;}if(t>2) break;}cout<<"不正常方法:开始搜索......\n";dfs(1,1);
}
int main()
{read();work();return 0;
}
shudufa.h:
#ifndef SHUDUFA_H
#define SHUDUFA_H
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P; P ji[11];
int kuai[11][11],lie[11][11],hang[11][11],ma[11][11],k,mm[11][11];
inline int d(int pd,int x,int y) {if(pd==1) return x; else return y;}
inline int find(int num)
{int jinum=0;for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) if(ma[i][j]==num) ji[++jinum]=P(i,j);return jinum;
}
inline void biao_hui(int p,int x,int y,int val,int howk)
{hang[x][val]=p;lie[y][val]=p;kuai[howk][val]=p;mm[x][y]=1;ma[x][y]=p*val;k+=2*p-1;
}
inline void does(int i1,int i2,int j1,int j2,int temp[11][11],int num,int howk)
{int sum=0,x,y; for(int i=i1;i<=i2;i++){for(int j=j1;j<=j2;j++){if(temp[i][j]) sum++;else x=i,y=j;}}if(sum==8&&kuai[howk][num]==0) biao_hui(1,x,y,num,howk);
}
inline void tian(int shu,int num)
{int temp[11][11];for(int j=1;j<=9;j++) for(int kk=1;kk<=9;kk++) temp[j][kk]=mm[j][kk];for(int i=1;i<=shu;i++){int x=ji[i].first,y=ji[i].second;for(int j=1;j<=9;j++) temp[x][j]=temp[j][y]=1;}for(int i=1;i<=3;i++){int xr=i*3,xl=xr-2;for(int j=1;j<=3;j++) does(xl,xr,(j-1)*3+1,j*3,temp,num,(i-1)*3+j);}
}
inline void does2(int pd)
{if(pd==0){for(int i=1;i<=9;i++) tian(find(i),i);return;}for(int i=1;i<=9;i++){queue<int> q;int use[11],bu=0;memset(use,0,sizeof(use)); for(int j=1;j<=9;j++){if(!hang[d(pd,i,j)][d(pd,j,i)]){q.push(d(pd,j,i));use[d(pd,j,i)]=1;bu++;}}for(int j=1;j<=9;j++){if(ma[d(pd,i,j)][d(pd,j,i)]) continue;int num=(d(pd,i,j)-1)/3*3+(d(pd,j,i)-1)/3+1;for(int ki=1;ki<=9;ki++){if(use[ki]){int uu=0;for(int kk=1;kk<=9;kk++){if(use[kk]&&ki!=kk){if(kuai[num][kk]||hang[d(pd,i,j)][kk]||lie[d(pd,j,i)][kk]) uu++;}}if(uu==bu-1&&!kuai[num][ki]&&!hang[d(pd,i,j)][ki]&&!lie[d(pd,j,i)][ki]){bu--;use[ki]=0;biao_hui(1,d(pd,i,j),d(pd,j,i),ki,num);}}}}}
}
#endif
reawri.h:
#ifndef REAWRI_H
#define REAWRI_H
#include"shudufa.h"
#include<bits/stdc++.h>
using namespace std;
inline void print(int mmm[11][11])
{for(int i=1;i<=9;i++){for(int j=1;j<=9;j++) cout<<mmm[i][j]; cout<<endl;}cout<<endl;
}
inline void read()
{for(int i=1;i<=9;i++){for(int j=1;j<=9;j++){cin>>ma[i][j];if(ma[i][j]) {int num=(i-1)/3*3+(j-1)/3+1;biao_hui(1,i,j,ma[i][j],num);}}}
}
#endif
C++实现数独(附带过程)相关推荐
- 使用C#编程解决数独求解过程(从图片识别到数独求解)第二篇
这是在C#开发平台上借助Emgucv和Tessnet实现的,通过图像识别的方式求解手机app中"数独"应用中的九宫格. 预处理:emgucv-windesktop 3.1.0.22 ...
- 基于C++和QT实现的简单数独游戏软件
资源下载地址:https://download.csdn.net/download/sheziqiong/85660211 一.实验题目与要求 本次实验主要内容是实现一个简单的数独软件,具体要求如下: ...
- C语言简单数独游戏终盘生成
前言 这一篇文章介绍的是移动变换法,有详细的移动变化法的图文解析,在文末有完整的可用于查看移动变换法生成数独终盘过程的代码 实现思路 移动变换法这一方法是很简单的一种方法,实现起来也比较容易,但同时它 ...
- 【习题·搜索】[NOIP2009]靶型数独(搜索+剪枝+位运算优化)
题目 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的&quo ...
- 软件工程大作业——数独游戏
软件工程大作业--数独游戏1 一.PSP表格 二.问题分析 三.系统设计 四.具体实现 五.单元测试 六.程序性能及质量分析 七.GUI 八.总结 代码地址:https://github.com/fr ...
- cobbler 无人值守-安装
环境准备 准备两台主机,如centos6和centos7 centos7当作server服务器 关闭selinux 关闭防火墙 安装 cobbler包光盘里是没有的,要配置epel源,这里就说怎么配置 ...
- 怎么用纸做圆形的盒子_如何培养孩子逻辑思维能力?抓住0-8岁关键期,聪明的家长这样做...
最近和朋友聊天,他特别苦恼和纳闷:我的孩子幼儿园和刚进入小学时成绩总是名列前茅,怎么越往后成绩越差,这是为什么呢? 这种现象还是挺经常出现的,幼儿园和小学1-3年级阶段,孩子努力用功是可以取得好成绩的 ...
- 幼儿抽象逻辑思维举例_孩子逻辑思维能力有多重要?巧用生活小游戏,培养好了娃受益终身...
最近和朋友聊天,他特别苦恼和纳闷:我的孩子幼儿园和刚进入小学时成绩总是名列前茅,怎么越往后成绩越差,这是为什么呢? 这种现象还是挺经常出现的,幼儿园和小学1-3年级阶段,孩子努力用功是可以取得好成绩的 ...
- 2019软件工程第三次作业
2019软件工程第三次作业 数独游戏 戳这里进入Github项目 第一眼看到要做数独的时候,脑海里的第一反应就是用深搜.现在好了,确定了算法,接下来就是要去实现它,可是对于将近半年没写过深搜的我要写一 ...
最新文章
- GaussianBlur函数
- 右键删除选中的行总提示rowIndex
- 读书记:asp.net2.0电子商务开发实战
- 给lnmp一键包中的nginx安装openresty的lua扩展
- 自动采集壁纸的微信小程序
- Java实现单词树(trie)
- Zend Framework实例教程三
- IOCP的Demo及说明
- Python装饰器的原理与应用
- 河北2021高考成绩查询具体时间,2021河北高考时间具体安排表
- 2020五一建模:C题 饲料混合加工问题 题解
- 【LED灯屏控制器】国产FPGA之 AG10KSDE176 初探(1)
- kvm虚拟机管理工具列表
- php天籁吉他乐器介绍网站系统
- 《全民学乒乓》学习笔记
- 3 继续测试一下 esp_tunnel 用 racoon协商 用setkey设置 spd
- 深度学习超分辨率综述阅读笔记(翻译)
- 魔众EDM邮件营销系统 v1.0.0 专业的EDM邮件营销系统
- Guides-旅游类App原型分享
- 复旦大学计算机学院肖江,【学术报道】复旦大学肖江教授应邀来我校学术交流...
热门文章
- WPF中ListView排序实现(2022.12.25有更新)
- 华为交换机ssh思科交换机_如何在思科交换机上配置SSH远程登录
- capsule 安装_Capsule:开源的 JVM 应用部署工具
- 台湾通行证识别易语言代码
- spark on k8s中指定spark.executor.instances为3,却没有启动executor的pod分析与解决
- 正月初五迎财神抢红包发红包!红包封面不能少!红包财源滚滚快来领取
- 为Notepad++安装Emmet插件
- Python 实现文本解析器
- 2021-2022年十类(30+)热门资质证书汇总分享,
- delphi mysql 图片_如何读取delphi数据库中的图片