数独程序

来源:互联网 发布:mysql联表查询效率 编辑:程序博客网 时间:2024/05/22 14:59

//

//  su.h

//  sudo

//

//  Created by thw on 2017/8/8.

//  Copyright © 2017 thw. All rights reserved.

//


#ifndef su_h

#define su_h


#include <stack>

#include <iostream>


/*

int sudo[9][9] = {

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0,0,

};

 */

/*

int sudo[9][9]={

    0,1,0,0,0,3,0,5,0,

    3,0,0,0,0,5,0,0,2,

    0,0,0,8,0,0,0,1,0,

    7,0,8,0,3,0,1,2,0,

    2,9,0,0,0,0,0,7,3,

    0,3,6,0,2,0,4,0,5,

    0,7,0,0,0,2,0,0,0,

    6,0,0,4,0,0,0,0,7,

    0,2,0,9,0,0,0,6,0};

 */


int sudo[9][9] = {

    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,

};


std::stack<int> stack[9][9];//当前sudo上行列位置上可填数字栈


//sudo坐标左右小九格偏移

int gLeft[9] = {0,1,2,0,1,2,0,1,2};

int gRight[9] = {2,1,0,2,1,0,2,1,0};

//sudo坐标上下小九格偏移

int gTop[9] = {0,1,2,0,1,2,0,1,2};

int gBottom[9] = {2,1,0,2,1,0,2,1,0};


//搜索pos路径

typedef struct _Pos

{

    int i;

    int j;

    std::stack<int> values;

}Pos;

std::stack<Pos> posStack;


void printSudo()

{

    for (int i =0; i< 9; i++){

        for (int j =0; j < 9 ;j++){

            std::cout<<sudo[i][j];

            if ((j+1) %3 ==0){

                std::cout<<"|";

            }

            else{

                std::cout<<" ";

            }

        }

        std::cout <<std::endl;

        if ((i+1)%3==0) {

            for (int j =0; j < 9 ;j++){

                std::cout<<"- ";

            }

            std::cout <<std::endl;

        }

    }

    std::cout <<std::endl;

}

bool okSudo()

{

    for (int i =0; i< 9; i++){

        for (int j =0; j < 9 ;j++){

            if (sudo[i][j] ==0)

                returnfalse;

        }

    }

    returntrue;

}

void clearStack(int i,int j)

{

    while (!stack[i][j].empty()) {

        stack[i][j].pop();

    }

}

//获取si,sj位置上的可填数字栈

void getStack(int si,int sj)

{

    int temparr[10] = {0,1,2,3,4,5,6,7,8,9};

    //移除对应的大九宫格行列上数字

    for (int j =0; j< 9; j++){

        temparr[sudo[si][j]] =0;

    }

    for (int i =0; i< 9; i++){

        temparr[sudo[i][sj]] =0;

    }

    //移除小九宫格内对应数字

    int left =gLeft[sj];

    int right =gRight[sj];

    int top =gTop[si];

    int bottom =gBottom[si];

    int min_x = si-top;

    int min_y = sj-left;

    int max_x = si+bottom;

    int max_y = sj+right;

    for (int i = min_x; i <= max_x;i++){

        for (int j = min_y; j <= max_y;j++)

            temparr[sudo[i][j]] =0;

    }

    //可填数字入栈

    for (int i =1; i < 10; i++){

        if (temparr[i] !=0){

            stack[si][sj].push(temparr[i]);

        }

    }

}


bool backOldPos()

{

    while (!posStack.empty()){

        Pos& backPos =posStack.top();

        if (backPos.values.empty()){

           //此位置已无可填数字,回退上一个位置

            sudo[backPos.i][backPos.j] =0;

            posStack.pop();

        }

        else{

            //回退一个可填数字

            sudo[backPos.i][backPos.j] = backPos.values.top();

            backPos.values.pop();

            returntrue;

        }

    }

    //路径完毕,表示无解了

    returnfalse;

}

static int placeNewPosCnt =0;

bool placeNewPos()

{

    placeNewPosCnt++;

    //设置后面所有新可填位置的数字堆栈

    for (int i =0; i< 9; i++){

        for (int j =0; j < 9 ;j++){

            if (sudo[i][j] ==0){

                clearStack(i, j);

                getStack(i,j);

            }

        }

    }

    

    //找一个新可填位置,策略:找可填数字最少的新位置

    Pos curPos;

    int minLen =10;

    for (int i =0; i< 9; i++){

        for (int j =0; j < 9 ;j++){

            if (sudo[i][j] ==0 && !stack[i][j].empty() &&stack[i][j].size()<minLen){

                curPos.i = i;

                curPos.j = j;

                minLen = (int)stack[i][j].size();

            }

        }

    }

    if (minLen ==10){

        //无新位置可设置

        returnfalse;

    }

    

    //找到新位置,新位置填一个数字,此位置其他可填数字入位置栈,待回溯时调用

    sudo[curPos.i][curPos.j] =stack[curPos.i][curPos.j].top();

    stack[curPos.i][curPos.j].pop();

    while (!stack[curPos.i][curPos.j].empty()){

        curPos.values.push(stack[curPos.i][curPos.j].top());

        stack[curPos.i][curPos.j].pop();

    }

    posStack.push(curPos);

    returntrue;

}


void killSudo()

{

    while (placeNewPos()){

        ;//往前找,直到无法找到可填数字

    }

    if (okSudo())

    {

        std::cout<<"ok,placeNewPos count : " << placeNewPosCnt <<std::endl;

        printSudo();

        return;

    }

    //回溯路径

    if (!backOldPos()){

        std::cout<<"failed"<<std::endl;

        printSudo();

        return;

    }

    //回溯一个数字后,继续递归往前找

    killSudo();

}


#endif /* su_h */


原创粉丝点击