数独问题流程图_数独求解算法
前言
周末兩天,閑來(lái)無(wú)事,于是花了半天把自己很久就想研究的數(shù)獨(dú)求解進(jìn)行了算法實(shí)現(xiàn)。
初級(jí)玩法
首先看一下數(shù)獨(dú)
屏幕快照 2018-03-25 下午6.30.52.png
數(shù)獨(dú)規(guī)則
數(shù)獨(dú)的規(guī)則比較簡(jiǎn)單:
每一行包括了1到9的數(shù)字,并且不能重復(fù)。
每一列包括了1到9的數(shù)字,并且不能重復(fù)。
每一組包括了1到9的數(shù)字,并且不能重復(fù)。
玩數(shù)獨(dú)求解的流程
步驟一:從上到下,從左到右選擇一個(gè)空單元。
步驟二: 根據(jù)這個(gè)單元所在的行、列、組,求出這個(gè)單元可能的解。
步驟三:隨機(jī)抽取一個(gè)未論證的解作為單元的解進(jìn)行填入,進(jìn)行步驟一。
步驟四:如果步驟三中這個(gè)單元的所有未論證的解為空,則說(shuō)明上一次隨機(jī)填入有誤。機(jī)型步驟五。
步驟五:退到上一個(gè)單元,將上一次隨機(jī)填入解從未論證隨機(jī)解中刪除,進(jìn)行步驟三。
步驟六:如果步驟二中這個(gè)單元的所有可能解為空,則說(shuō)明上一次隨機(jī)填入有誤,進(jìn)行步驟五。
步驟七:如果發(fā)現(xiàn)已經(jīng)無(wú)法選擇單元,即單元已經(jīng)填滿(mǎn),說(shuō)明完成解數(shù)獨(dú)。
流程圖:
shuduprocess.jpg
總體而言,整個(gè)過(guò)程是一個(gè)選擇空單元,求合適解,選擇未論證解,論證,論證之后再返回的過(guò)程。
代碼實(shí)現(xiàn)
算法的實(shí)現(xiàn)步驟
輸入
獲取一個(gè)大小為81的范圍為0-9的整型數(shù)組,0代表空。
新建一個(gè)9*9的二維單元結(jié)點(diǎn)數(shù)組,每個(gè)節(jié)點(diǎn)保存節(jié)點(diǎn)的位置,并將整形數(shù)組的值傳給節(jié)點(diǎn)。
新建9個(gè)列的節(jié)點(diǎn)數(shù)組集合,9個(gè)行的節(jié)點(diǎn)數(shù)組集合,9個(gè)組的節(jié)點(diǎn)數(shù)組集合。每個(gè)節(jié)點(diǎn)保存保存所在列的節(jié)點(diǎn)數(shù)組集合,所在行的節(jié)點(diǎn)數(shù)組結(jié)合,所在組的節(jié)點(diǎn)數(shù)組結(jié)合。
輸入代碼
private void initData(char[] charArray) {
//新建各個(gè)節(jié)點(diǎn)對(duì)應(yīng)步驟二
soduNodes = new SoduNode[9][9];
for (int i = 0; i < 9; i++) {
for (int k = 0; k < 9; k++) {
SoduNode soduNode = new SoduNode();
soduNode.value=charArray[i*9+k]-'0';
soduNode.xPosition=k;
soduNode.yPosition=i;
soduNodes[i][k]=soduNode;
}
}
//每個(gè)節(jié)點(diǎn)保存保存所在列的節(jié)點(diǎn)集合,所在行的節(jié)點(diǎn)集合,所在組的結(jié)合。對(duì)應(yīng)步驟三
for(int i=0 ;i<9;i++){
SoduNode [] listNode=new SoduNode[9];
for(int k=0;k<9;k++){
listNode[k]=soduNodes[i][k];
soduNodes[i][k].listNode=listNode;
}
System.out.println("listNode:"+SoduNode.getNodesValue(listNode));
}
for(int i=0 ;i<9;i++){
SoduNode [] rowNode=new SoduNode[9];
for(int k=0;k<9;k++){
rowNode[k]=soduNodes[k][i];
soduNodes[k][i].rowNode=rowNode;
}
System.out.println("rowNode:"+SoduNode.getNodesValue(rowNode));
}
for(int i=0;i<=2;i++){
for(int k=0;k<=2;k++){
SoduNode [] groupNode=new SoduNode[9];
int index=0;
int middlex=3*i+1;
int middley=3*k+1;
for(int j=-1;j<=1;j++){
for(int l=-1;l<=1;l++){
groupNode[index]=soduNodes[middlex+j][middley+l];
soduNodes[middlex+j][middley+l].groupNode=groupNode;
index++;
}
}
System.out.println("groupNode:"+SoduNode.getNodesValue(groupNode));
}
}
}
求解
代碼求解過(guò)程與玩數(shù)獨(dú)的流程基本一致:
核心代碼
//對(duì)應(yīng)步驟一
private boolean getNextNodeAndCheck() {
SoduNode lastNullNode = getNextNullNode(); //步驟二
if(lastNullNode==null){
return true;
} //對(duì)應(yīng)步驟七
Integer[] suitValue = lastNullNode.getSuitValue();
if(suitValue==null||suitValue.length==0){
System.out.println("no have suitable value");
return false;
}//對(duì)應(yīng)步驟六
for(int i=0;i
lastNullNode.value=suitValue[I];//步驟三
//對(duì)應(yīng)步驟一
if(getNextNodeAndCheck()){
return true;
}
}
return false;//所有可能解都已經(jīng)論證完,無(wú)需論證解,對(duì)應(yīng)步驟四
}
獲取可能解的過(guò)程
Integer[] getSuitValue() {
TreeSet notSuits = new TreeSet<>();
TreeSet allValue= new TreeSet();
for (int i = 0; i <= 8; i++) {
if (listNode[i].value != 0) {
notSuits.add(listNode[i].value);
}
if (rowNode[i].value != 0) {
notSuits.add(rowNode[i].value);
}
if (groupNode[i].value != 0) {
notSuits.add(groupNode[i].value);
}
allValue.add(allChar[i]);
}
int notSuitSize = notSuits.size();
if (notSuitSize == 9) {
return null;
}
allValue.removeAll(notSuits);
System.out.println("allValue :" + getTreeValue(allValue));
Integer[]suitValue=new Integer[allValue.size()];
Iterator iterator = allValue.iterator();
int suitValueIndex=0;
while(iterator.hasNext()){
suitValue[suitValueIndex]=iterator.next();
suitValueIndex++;
}
System.out.println("suitValue size:"+suitValue.length+" value:"+getSuitsValue(suitValue));
return suitValue;
}
獲取可能解的邏輯為
1.獲取節(jié)點(diǎn)所在列、行、組所有存在的值的集合
2.將一個(gè)1到9的集合減掉存在值的集合即為可能解
運(yùn)行
將上圖數(shù)獨(dú)求解
請(qǐng)輸入81個(gè)數(shù)字代表數(shù)獨(dú):/n
009100000040078023600402001032680057895000030064310000407863915008590762956721040
initdata is :
0 0 9 1 0 0 0 0 0
0 4 0 0 7 8 0 2 3
6 0 0 4 0 2 0 0 1
0 3 2 6 8 0 0 5 7
8 9 5 0 0 0 0 3 0
0 6 4 3 1 0 0 0 0
4 0 7 8 6 3 9 1 5
0 0 8 5 9 0 7 6 2
9 5 6 7 2 1 0 4 0
resut is :
2 8 9 1 3 6 5 7 4
5 4 1 9 7 8 6 2 3
6 7 3 4 5 2 8 9 1
1 3 2 6 8 9 4 5 7
8 9 5 2 4 7 1 3 6
7 6 4 3 1 5 2 8 9
4 2 7 8 6 3 9 1 5
3 1 8 5 9 4 7 6 2
9 5 6 7 2 1 3 4 8
聯(lián)系我
總結(jié)
以上是生活随笔為你收集整理的数独问题流程图_数独求解算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Centos7搭建Java环境,并设置项
- 下一篇: 小程序自带git方法提交时文件冲突的解决