回溯法简单讲就是循环+递归,教材是从八皇后问题开始讲。
一开始对递归理解不深,这个数独作业写了几天。递归有点数学中的数列,有a(n+1)=f(a(n));得出相邻两步关系。最重要的要加上递归结束条件。而退出递归的过程,函数也是一层一层退出!
再讲讲用回溯解答数独(要求每行,每列,每个小九宫格的数字不同),
for(char num='1';num<='9';num++){ //这就是开始所说的循环
检查当前格子是否符合要求 ,符合就填写下一个格子 //这就是开始说的递归过程
}
附近中是我读取的txt
具体c++代码;
Sudoku.h头文件
#ifndef SUDOKU_H
#define SUDOKU_H
#include<iostream>
#include<fstream>
#include <string>
using namespace std;
class Sudoku{
private:
char element[9][9];
char save[9][9]; //保存数独结果,用于写入txt
bool isValid(const int &row=0,const int &column=0); //判断当前格子里数字是否合格
void backtrace(int row=0,int column=0); //回溯核心算法
public:
Sudoku();
void input(const string &fileName); //读取txt成员函数
void solve(); //解答数独,并输出控制台成员函数
void output(const string &fileName);//写入txt成员函数
};
#endif // !SUDOKU_H
------------------------------------------------------------------
Sudoku.cpp源文件
/**********回溯法**********/
#include "Sudoku.h"
Sudoku::Sudoku(){
for(int i=0;i<9;i++)
for(int j=0;j<9;j++){
element[i][j]='0';
save[i][j]='0';
}
}
bool Sudoku::isValid(const int &row,const int &column){
for(int j=0;j<9;j++) // 检验行是否符合条件
if(element[row][j]==element[row][column]&&j!=column)
return false;
for(int i=0;i<9;i++) //检查列是否符合
if(element[i][column]==element[row][column]&&i!=row)
return false;
for(int i=row/3*3;i<row/3*3+3;i++) //检测小的九宫格是否符合
for(int j=column/3*3;j<column/3*3+3;j++)
if(element[i][j]==element[row][column]&&i!=row&&j!=column)
return false;
return true;
}
void Sudoku::backtrace(int row,int column){ //回溯法核心代码
if(row>8){ //最后一层递归结束,并打印结果
cout<<"The result:"<<endl;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
save[i][j]=element[i][j];
cout<<save[i][j];
}
cout<<endl;
}
return;
}
for(;row<9;row++){ //找出'0',即代表未知格子
for(;column<9;column++)
if(element[row][column]=='0')
break;
if(column==9)
column=0;
if(element[row][column]=='0')
break;
}
for(char num='1';num<='9';num++){ //逐个尝试
element[row][column]=num;
if(isValid(row,column)){
if(column<8)
backtrace(row,column+1); //递归
else if(row<9)
backtrace(row+1,0);//递归
}
}
element[row][column]='0'; //当前层次不符合条件是,置'0'回溯
}
void Sudoku::solve(){
backtrace(0,0);
}
void Sudoku::input(const string &fileName){
ifstream fin;
string line;
fin.open(fileName.c_str());
if(!fin){ //判断文件是否正常打开
cout<<"Unable to open the file!"<<endl;
exit(1);
}
int i=0;
while(getline(fin,line)){ //逐行读取输入流中的文件,直至该输入流结束
for(int j=0;j<9;j++)
element[i][j]=line[j]; //提取字符串中的每个字符
i++;
}
fin.close(); //关闭文件
cout<<"The input:"<<endl; //输出原始数据到控制台
for(int i=0;i<9;i++){
for(int j=0;j<9;j++)
cout<<element[i][j];
cout<<endl;
}
}
void Sudoku::output(const string &fileName){
ofstream fout(fileName.c_str());
if(!fout){
cout<<"error!"<<endl;
exit(1);
}
for(int i=0;i<9;i++){
for(int j=0;j<9;j++)
fout<<save[i][j]; //逐个写入输出文件
fout<<endl;
}
fout.close();
}
--------------------------------------------------------------------------------------------------------------------------------------------
main.cpp#include "Sudoku.h"
void main(int argc,char *argv[]){
Sudoku mySudoKu;
if(argc!=3){
cout<<"please input the program,the address of input txt and address of output txt like this:"<<endl;
cout<<" "<<"Sudoku.exe ***.txt(for input) ***.txt(for output)"<<endl;
exit(1);
}
mySudoKu.input(argv[1]);
//mySudoKu.input("G:\\研究生一年级\\人工智能\\作业\\149409758_1_homework1\\homework1\\test1.txt");
mySudoKu.solve();
//mySudoKu.output("G:\\研究生一年级\\人工智能\\作业\\149409758_1_homework1\\homework1\\output.txt");
mySudoKu.output(argv[2]);
//getchar();
}