我们知道,每个宫内必须包含数字9,第1宫以及第3宫中都包含数字9,并且第1宫的9位于第3行。
第3宫的9位于第2行,这也就意味着第2宫的9不能在第2行和第3行,所有第2宫的9只能放置在第2宫第1行的空格内。
2.双向扫看法:同样的技巧也可以扩展到相互垂直的行与列中。让我们想一下第3宫中1应该放在哪里。在这个例子中,第1行以及第2行已经有1了,那么第3宫中只有底部的俩个空格可以填1。不过,方格g4已经有1了,所有第g列不能再有1。
所以i3是该宫唯一符合条件填上数字1的地方。
3.寻找候选法:通常地,一个方格只能有一个数字的可能性,因为剩下的其他8个数字都已经被相关的行列宫所排除了。我们看一下下面例子中b4这个方格。b4所在的宫中已经存在了数字3,4,7,8,1和6位于同一行,5和9位于同一列,排除上述所有数字,b4只能填上2。
4数字排除法:排除法是一个相对繁杂的寻找数字的方法。我们可以从c8中的1间接推出e7和e9必须包含数字1,不管这个1在哪个方格,我们可以确认的是,第e列的数字1肯定在第8宫内,所以第2宫内中间这一列就不可能存在数字1。因此,第2宫的数字一必须填在d2处。
前两天刚写完,还没优化,已运行通过了.晕,一维的好麻烦,这个也是碰巧前两天刚写好的,你看着自己修改下
#include <stdio.h>
typedef struct
{
int line
int row
int num
}Node
int main()
{
/*
int a[9][9]={
{4,0,3,6,0,0,0,0,0},
{0,0,0,0,0,1,0,2,4},
{0,1,0,0,4,0,5,0,0},
{0,0,0,9,0,4,0,6,0},
{3,0,2,0,0,0,4,0,9},
{0,7,4,1,0,3,0,0,0},
{0,0,1,0,9,0,0,4,0},
{2,4,0,3,0,0,0,0,0},
{0,0,0,4,0,8,2,0,7}}
*/
int a[9][9]={
{0,0,0,8,0,0,0,6,0},
{8,7,0,0,0,0,0,0,0},
{2,9,0,0,4,1,0,0,5},
{0,0,5,7,0,0,0,0,9},
{0,2,0,0,0,0,0,1,0},
{9,0,0,0,0,4,3,0,0},
{7,0,0,6,1,0,0,9,8},
{0,0,0,0,0,0,0,5,2},
{0,6,0,0,0,9,0,0,0}}
/*
int a[9][9]={
{0,2,0,0,6,0,0,0,0},
{0,9,0,4,0,5,1,3,0},
{0,0,8,7,0,0,0,0,5},
{6,0,0,3,0,0,4,0,0},
{0,0,0,9,0,6,0,0,0},
{0,0,7,0,0,1,0,0,3},
{4,0,0,0,0,7,3,0,0},
{0,8,5,2,0,4,0,7,0},
{0,0,0,0,9,0,0,1,0}}
*/
/*
int a[9][9]={
{0,0,3,0,2,0,0,0,6},
{0,0,2,0,9,0,0,0,4},
{7,0,0,8,0,0,2,0,3},
{0,8,0,0,7,0,5,0,0},
{0,7,0,1,0,6,0,3,0},
{0,0,0,2,0,0,0,9,0},
{4,0,6,0,0,8,0,0,5},
{6,0,0,0,4,0,3,0,0},
{9,0,0,0,1,0,7,0,0}}
*/
int i,j,n,en,flag,y,k=0,x,qu,p,q
Node b[70]
for(i=0i<9i++)
{
for(j=0j<9j++)
{
if(!a[i][j])
{
b[k].line=i
b[k].row=j
b[k].num=0
k+=1
}
}
}
en=k
/*从b[0]开始试,若b[k].num>9,则k-1,否则k+1*/
for(k=0k<en)
{
++b[k].num
i=b[k].line
j=b[k].row
a[i][j]=b[k].num
n=0
while(n<9&&b[k].num<=9)
{
if(n==i)
{
for(y=0y<9y++)
{
if(y==j)
continue
if(a[n][y]==a[i][j])
flag=1
}
}
else if(n==j)
{
for(y=0y<9y++)
{
if(y==i)
continue
if(a[y][n]==a[i][j])
flag=1
}
}
/*判断同一块中有没有相同值*/
qu=3*(i/3)+j/3
switch(qu)
{
case 0:x=0
y=0
break
case 1:x=0
y=3
break
case 2:x=0
y=6
break
case 3:x=3
y=0
break
case 4:x=3
y=3
break
case 5:x=3
y=6
break
case 6:x=6
y=0
break
case 7:x=6
y=3
break
default :x=6
y=6
break
}
p=x
q=y
for(x<p+3x++)
{
for(y<q+3y++)
{
if(x==i&&y==j)
continue
if(a[x][y]==a[i][j])
{
flag=1
break
}
}
if(flag==1)
break
}
if(flag==1)
{
a[i][j]=++b[k].num
flag=0
n=0
continue
}
n++
}
if(b[k].num>9)
{
a[i][j]=b[k].num=0
k--
if(k<0)
{
printf("error!\r\n")
return -1
}
}
else
k++
}
for(i=0i<9i++)
{
for(j=0j<9j++)
{
printf("%d",a[i][j])
}
printf("\r\n")
}
return 1
}
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
解题手法
依解题填制的过程可区分为直观法与候选数法。
直观法就是不做任何记号,直接从数独的盘势观察线索,推论答案的方法。
候选数法就是删减等位群格位已出现的数字,将剩余可填数字填入空格做为解题线索的参考,可填数字称为候选数(Candidates,或称备选数)。
直观法和候选数法只是填制时候是否有注记的区别,依照个人习惯而定,并非鉴定题目难度或技巧难度的标准,无论是难题或是简单题都可上述方法填制,一般程序解题以候选数法较多。
摒除法
摒除法:用数字去找单元内唯一可填空格,称为摒除法,数字可填唯一空格称为摒余解(Hidden Single)。
根据不同的作用范围,摒余解可分为下述三种:
数字可填唯一空格在「宫」单元称为宫摒余解(Hidden Single in Box),这种解法称宫摒除法。
数字可填唯一空格在「行」单元称为行摒余解(Hidden Single in Row),这种解法称行摒除法。
数字可填唯一空格在「列」单元称为列摒余解(Hidden Single in Column),这种解法称列摒除法。
行摒余解和列摒余解合称行列摒余解(Hidden Single in Line)。
得到行列摒余解的方法称为行列摒除法。
余数法
Peer等位群格位
余数法:用格位去找唯一可填数字,称为余数法,格位唯一可填数字称为唯余解(Naked Single)。
余数法是删减等位群格位(Peer)已出现的数字的方法,每一格位的等位群格位有 20 个,如图七所示。
进阶解法
上述方法称为基础解法(Basic Techniques),其他所有的解法称为进阶解法(Advanced Techniques),是在补基本解法之不足,所以又称辅助解法。
进阶解法包括:区块摒除法(Locked Candidates)、数组法(Subset)、四角对角线(X-Wing)、唯一矩形(Unique Rectangle)、全双值坟墓(Bivalue Universal Grave)、单数链(X-Chain)、异数链(XY-Chain)及其他数链的高级技巧等等。已发展出来的方法有近百种之多。
其中前三种加上基础解法为一般数独书中介绍并使用的方法,同时也是大部分人可以理解并掌握的数独解题技法。
通过基础解法出数只需一种解法,摒除法或唯余法,超出此范围而需要施加进阶解法时,解题点需要进阶解法协助基础解法来满足隐性唯一或显性唯一才能出数,该解题点的解法需要多个步骤协力完成,因此称做组合解法。
解题必须以逻辑为依归,猜测的方法被称为暴力型解法(Brute Force),这不是提倡数独的本意。
区块摒除法
区块摒除法包括宫区块摒除法(Pointing)与行列区块摒除法(Claiming)。
在基础题里,利用区块摒除可以替代一些基础解法的观察,或辅助基础解法寻找焦点。
在非基础题里,区块可以隐藏任何其他结构,简单的可以把基础解法隐藏起来,难的可以隐藏数对等等其他进阶技巧。
区块摒除法
首先数字6对第五宫摒除,得到第五宫的6在R4C5或者R6C5。
不论是在R4C5或者R6C5,C5的其他格都不能再有数字6。(R4C5与R6C5就是数字6的区块,这也是区块摒除作用的观点)
数字6对第二宫摒除,得解R1C4=6。
数对法
当一个单元(行、列、宫)的某两个数字仅可能在某两格时,我们称这两个格为这两个数的数对(Pairs)。
数对出现在宫称为宫数对;数对出现在行列成为行列数对。
用候选数法的观点去看,数对有两种,一种是在同单元内其中两格有相同的双候选数,一看就明白,因此称为显性数对(Naked Pair),另一种是,同单元内有两个候选数占用了相同的两格,该两格因为还有其它候选数很难辨认,因此称为隐性数对(Hidden Pair)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)