To 洛谷.1784 数独类似题:CODEVS.4966 简单数独(4*4数独) CODEVS.2924 数独挑战

题目描述

数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的。

芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战。

这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这个“数独之谜”。

据介绍,目前数独游戏的难度的等级有一道五级,一是入门等级,五则比较难。不过这位数学家说,他所设计的数独游戏难度等级是十一,可以说是所以数独游戏中,难度最高的等级他还表示,他目前还没遇到解不出来的数独游戏,因此他认为“最具挑战性”的数独游戏并没有出现。

输入输出格式

输入格式:

一个未填的数独

输出格式:

填好的数独

输入输出样例

输入样例#1: 复制

8 0 0 0 0 0 0 0 0
0 0 3 6 0 0 0 0 0
0 7 0 0 9 0 2 0 0
0 5 0 0 0 7 0 0 0
0 0 0 0 4 5 7 0 0
0 0 0 1 0 0 0 3 0
0 0 1 0 0 0 0 6 8
0 0 8 5 0 0 0 1 0
0 9 0 0 0 0 4 0 0
输出样例#1: 复制

8 1 2 7 5 3 6 4 9
9 4 3 6 8 2 1 7 5
6 7 5 4 9 1 2 8 3
1 5 4 2 3 7 8 9 6
3 6 9 8 4 5 7 2 1
2 8 7 1 6 9 5 3 4
5 2 1 9 7 4 3 6 8
4 3 8 5 2 6 9 1 7
7 9 6 3 1 8 4 5 2

[分析]:

用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝

bool row[10][10];    //row[i][x]  标记在第i行中数字x是否出现了

bool col[10][10];    //col[j][y]  标记在第j列中数字y是否出现了

bool g[10][10];   //g[k][x] 标记在第k个3*3子格中数字z是否出现了

row 和 col的标记比较好处理,关键是找出g子网格的序号与 行i列j的关系

即要知道第i行j列的数字是属于哪个子网格的

首先我们假设子网格的序号如下编排:

由于1<=i、j<=9,我们有: (其中“/”是C++中对整数的除法)

a= i/3 , b= j/3  ,根据九宫格的 行列 与 子网格 的 关系,我们有:

不难发现 3a+b=k

即 3*(i/3)+j/3=k

又我在程序中使用的数组下标为 1~9,grid编号也为1~9

因此上面的关系式可变形为 3*((i-1)/3)+(j-1)/3+1=k(第k个3*3子格中)

这样我们就能记录k个3*3子格中数字z是否出现了:

[代码]:

#include<cstdio>
#include<cstring>
#include<cstdlib>
int a[][];
bool h[][],l[][],g[][];//行,列,第几个格子
void print()//输出函数
{
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
printf("%d ",a[i][j]);
printf("\n");
}
exit();
} void dfs(int x,int y)//深搜
{
if(a[x][y]!=)//9*9中不为零的数直接跳过
{
if(x==&&y==)
print(); //搜索结束后输出
if(y==) //行到顶端后搜索列
dfs(x+,);
else //搜索行
dfs(x,y+);
}
if(a[x][y]==)//等于零时 待填数!
{
for(int i=;i<=;i++)
{ //true未访问过
if( h[x][i] && l[y][i] && g[(x-)/*+(y-)/+][i] ) //((i-1)/3)*3+(j-1)/3+1
{
a[x][y]=i; //从1试到9
h[x][i]=false;//此格被占 (行)
l[y][i]=false;//同上(列)
g[(x-)/*+(y-)/+][i]=false;//同上 (格子) if(x==&&y==) //同a[x][y]!=0时
print();
if(y==)
dfs(x+,);
else
dfs(x,y+); a[x][y]=; //当前格退出返回初状态
h[x][i]=true;
l[y][i]=true;
g[(x-)/*+(y-)/+][i]=true;
}
}
}
} int main()
{
memset(h,true,sizeof(h));
memset(l,true,sizeof(l));
memset(g,true,sizeof(g));
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]>)
{
h[i][a[i][j]]=false;//表示格子上有数
l[j][a[i][j]]=false;//同上
g[(i-)/*+(j-)/+][a[i][j]]=false;//同上
}
}
}
dfs(,);
puts("\n");
return ;
}

DFS

/*
根据二进制的思想,用二进制的第i位是0或1来表示数字是否已出现。
用 | 运算符进行标记,
用 ^ 运算符去标记,
用 & 运算符进行判重,
这样只需要一维的数组。
*/
#include<cstdio>
#define z(i) (1<<i)
#define g(x,y) (3*((x-1)/3)+(y-1)/3+1)
int h[],l[],s[],f[][],ok,sum=;
int read()
{
int _=,___=;char __=getchar();
while(__<''||__>''){if(__=='-')___=-;__=getchar();}
while(__>=''&&__<=''){_=_*+__-'';__=getchar();}
return _*___;
}
void out()
{
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
printf("%d ",f[i][j]);
printf("\n");
}
}
void dfs(int x,int y,int tot)
{
while(f[x][y])
{
y++;
if(y>) x++,y=;
}
for(int i=;i<=;i++)
{
if(h[x]&z(i)||l[y]&z(i)||s[g(x,y)]&z(i)) continue; //用 & 运算符进行判重 f[x][y]=i; h[x]|=z(i); l[y]|=z(i); s[g(x,y)]|=z(i); //用 | 运算符进行标记 if(tot==sum) ok=;
else dfs(x,y,tot+);
if(ok) return ; f[x][y]=; h[x]^=z(i); l[y]^=z(i); s[g(x,y)]^=z(i); //用 ^ 运算符去标记
}
}
int main()
{
for(int i=;i<=;i++)
for(int x,j=;j<=;j++)
{
f[i][j]=x=read();
if(!x)continue;
h[i]|=z(x); l[j]|=z(x); s[g(i,j)]|=z(x);
sum--;
}
dfs(,,);
out();
return ;
}

状态压缩dfs

洛谷 P1784 数独[DFS/回溯]的更多相关文章

  1. 洛谷P1784 数独

    To 洛谷.1784 数独(类似(或者说相同)题:CODEVS.4966 简单数独(4*4数独) CODEVS.2924 数独挑战) 题目描述 数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数 ...

  2. 洛谷 P1784 数独

    题目描述 数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字均含1-9,不重复.每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无 ...

  3. 洛谷—— P1784 数独

    https://www.luogu.org/problem/show?pid=1784 题目描述 数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字 ...

  4. P1074 靶形数独 dfs回溯法

    题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶 ...

  5. 填写数独 洛谷P1784

    题目链接:https://www.luogu.org/problemnew/show/P1784 因为要求行列以及每9个数字组成的中格子都得有1-9这9个数,我们不妨建三个二维数组 第一维代表是第几个 ...

  6. 【POJ - 2676】Sudoku(数独 dfs+回溯)

    -->Sudoku 直接中文 Descriptions: Sudoku对数独非常感兴趣,今天他在书上看到了几道数独题: 给定一个由3*3的方块分割而成的9*9的表格(如图),其中一些表格填有1- ...

  7. 洛谷P1731生日蛋糕(dfs+剪枝)

    P1731 生日蛋糕 题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M)层蛋糕是半径为R ...

  8. 洛谷1002 容斥原理+dfs OR DP

    //By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long ,,,,-,-,-,- ...

  9. luogu P1784 数独 dfs 舞蹈链 DXL

    LINK:数独 这道题好难 比DXL模板题要难上不少. 首先 还是考虑将行当做决策 那么 一共有\(9*9*9=729\) 个决策. 考虑列用来填充 需要有的条件为 某个位置能能放一次\(9*9\) ...

随机推荐

  1. A1012 The Best Rank (25)(25 分)

    A1012 The Best Rank (25)(25 分) To evaluate the performance of our first year CS majored students, we ...

  2. BFS:Nightmare(可返回路径)

    解题心得: 1.point:关于可以返回路径的BFS的标记方法,并非是简单的0-1,而是可以用时间比较之后判断是否push. 2.queue创建的地点(初始化问题),在全局中创建queue在一次调用B ...

  3. 3、python中的字符串

    一.前言 字符串是python中重要的数据类型.字符串就是一段文本,在python中用引号来标示. 二.字符串分类 字符串根据使用场景不同,一共分成3类: (1)单引号.双引号创建的单行字符串: 在单 ...

  4. Spring.Net初认识——竹子整理

    留个脚印,过两天总结. 看到知乎上有人对于DI|IOC 的解释,满不错,收藏下先 作者:OneNoodle链接:http://www.zhihu.com/question/23277575/answe ...

  5. vue时时监听input输入框中 输入内容 写法

    Vue input 监听 使用 v-on:input="change" 实现即可 App.vue <template> <div> <md-field ...

  6. datagrid的toolbar的两种实现方式

    datagrid的toolbar的两种实现方式 1.在html文件中,可以在设置toolbar="#tb",再在div中设置id="tb" <table ...

  7. Dsamain

    TechNet 库 Windows Server Windows Server 2008 R2 und Windows Server 2008 Windows Server 命令.参考和工具 Comm ...

  8. Java并发之(2):线程通信wait/notify(TIJ_21_5)

    简介: java中线程间同步的最基本的方式就是使用wait()&notify()&notifyAll(),它们是线程间的握手机制.除了上述方法,java5还在java.util.con ...

  9. jmeter正则表达式提取 引用

    jmeter正则表达式token提取 例: 添加正则 配置 token正则表达式:"token":"(.+?)" 模板:$1$ 添加信息头管理器进行配置 需要t ...

  10. hnust 土豪金的加密解密

    问题 G: 土豪金的加密与解密 时间限制: 1 Sec  内存限制: 128 MB提交: 466  解决: 263[提交][状态][讨论版] 题目描述     有一位姓金的同学因为买了一部土豪金,从此 ...