数独问题流程图_数独求解算法
前言
周末兩天,閑來無事,于是花了半天把自己很久就想研究的數獨求解進行了算法實現。
初級玩法
首先看一下數獨
屏幕快照 2018-03-25 下午6.30.52.png
數獨規則
數獨的規則比較簡單:
每一行包括了1到9的數字,并且不能重復。
每一列包括了1到9的數字,并且不能重復。
每一組包括了1到9的數字,并且不能重復。
玩數獨求解的流程
步驟一:從上到下,從左到右選擇一個空單元。
步驟二: 根據這個單元所在的行、列、組,求出這個單元可能的解。
步驟三:隨機抽取一個未論證的解作為單元的解進行填入,進行步驟一。
步驟四:如果步驟三中這個單元的所有未論證的解為空,則說明上一次隨機填入有誤。機型步驟五。
步驟五:退到上一個單元,將上一次隨機填入解從未論證隨機解中刪除,進行步驟三。
步驟六:如果步驟二中這個單元的所有可能解為空,則說明上一次隨機填入有誤,進行步驟五。
步驟七:如果發現已經無法選擇單元,即單元已經填滿,說明完成解數獨。
流程圖:
shuduprocess.jpg
總體而言,整個過程是一個選擇空單元,求合適解,選擇未論證解,論證,論證之后再返回的過程。
代碼實現
算法的實現步驟
輸入
獲取一個大小為81的范圍為0-9的整型數組,0代表空。
新建一個9*9的二維單元結點數組,每個節點保存節點的位置,并將整形數組的值傳給節點。
新建9個列的節點數組集合,9個行的節點數組集合,9個組的節點數組集合。每個節點保存保存所在列的節點數組集合,所在行的節點數組結合,所在組的節點數組結合。
輸入代碼
private void initData(char[] charArray) {
//新建各個節點對應步驟二
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;
}
}
//每個節點保存保存所在列的節點集合,所在行的節點集合,所在組的結合。對應步驟三
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));
}
}
}
求解
代碼求解過程與玩數獨的流程基本一致:
核心代碼
//對應步驟一
private boolean getNextNodeAndCheck() {
SoduNode lastNullNode = getNextNullNode(); //步驟二
if(lastNullNode==null){
return true;
} //對應步驟七
Integer[] suitValue = lastNullNode.getSuitValue();
if(suitValue==null||suitValue.length==0){
System.out.println("no have suitable value");
return false;
}//對應步驟六
for(int i=0;i
lastNullNode.value=suitValue[I];//步驟三
//對應步驟一
if(getNextNodeAndCheck()){
return true;
}
}
return false;//所有可能解都已經論證完,無需論證解,對應步驟四
}
獲取可能解的過程
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.獲取節點所在列、行、組所有存在的值的集合
2.將一個1到9的集合減掉存在值的集合即為可能解
運行
將上圖數獨求解
請輸入81個數字代表數獨:/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
聯系我
總結
以上是生活随笔為你收集整理的数独问题流程图_数独求解算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Centos7搭建Java环境,并设置项
- 下一篇: 小程序自带git方法提交时文件冲突的解决