[人工智能]回溯算法解数独
2017-10-25 17:06
1101 查看
今天在AI课上学了CSP,然后学了回溯算法。所以就用回溯算法来解数独吧。
数独问题可以把九九八十一个格简化为81个变量,每一个变量可以取1-9的值,当然,一开始初始化的值是不可以改变的。然后呢,对于这个数独呢,有3个约束条件:(1)每行数字不能重复;(2)每列数字不能重复;(3)每个3*3小区域内数字不能重复。
对于回溯算法,其实就是穷举,穷举出每个格子,也就是每个变量可能的值,如果该赋值不满足约束条件就回溯到上一个格进行下一个值的判断,直到穷举到最后一个格子,那就代表成功了。
代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int a[9][9] = {
{0,2,0,0,0,0,0,0,0},
{0,0,0,6,0,0,0,0,3},
{0,7,4,0,8,0,0,0,0},
{0,0,0,0,0,3,0,0,2},
{0,8,0,0,4,0,0,1,0},
{6,0,0,5,0,0,0,0,0},
{0,0,0,0,1,0,7,8,0},
{5,0,0,0,0,9,0,0,0},
{0,0,0,0,0,0,0,4,0}
};
int assign[81];
void print(){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
bool finish(int assign[])
{
for(int i = 0; i < 81; i++)
{
if(a[i / 9][i % 9] == 0)
{
return false;
}
}
return true;
}
bool judge(int x,int y){
for(int i=0;i<9;i++){
if(a[x][i]==a[x][y]&&i!=y)
return false;
}
for(int i=0;i<9;i++){
if(a[i][y]==a[x][y]&&i!=x)
return false;
}
for(int i=x/3*3;i<x/3*3+3;i++){
for(int j=y/3*3;j<y/3*3+3;j++){
if(a[i][j]==a[x][y]&&(i!=x||j!=y))
return false;
}
}
return true;
}
//int v = 0;
void BT(int level)
{
int v = 0;
if(finish(assign) == true)
{
print();
return;
}
while(assign[v] != 0)
{
v += 1;
}
//cout<<v<<endl;
if(assign[v] != 2)
{
assign[v] = 1;
for(int i = 1; i <= 9; i++)
{
a[v / 9][v % 9] = i;
bool constraintsOK = true;
if(judge(v / 9, v % 9) == false)
{
constraintsOK = false;
}
if(constraintsOK == true)
{
//print();
//system("pause");
BT(level + 1);
}
}
a[v / 9][v % 9] = 0;
assign[v] = 0;
//cout<< level<<endl;
return;
}
}
int main()
{
for(int i = 0; i < 81; i++)
{
if(a[i / 9][i % 9] != 0)
{
assign[i] = 2;
}
else
{
assign[i] = 0;
}
}
BT(0);
//cout<< finish(assign)<<endl;
}
数独问题可以把九九八十一个格简化为81个变量,每一个变量可以取1-9的值,当然,一开始初始化的值是不可以改变的。然后呢,对于这个数独呢,有3个约束条件:(1)每行数字不能重复;(2)每列数字不能重复;(3)每个3*3小区域内数字不能重复。
对于回溯算法,其实就是穷举,穷举出每个格子,也就是每个变量可能的值,如果该赋值不满足约束条件就回溯到上一个格进行下一个值的判断,直到穷举到最后一个格子,那就代表成功了。
代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int a[9][9] = {
{0,2,0,0,0,0,0,0,0},
{0,0,0,6,0,0,0,0,3},
{0,7,4,0,8,0,0,0,0},
{0,0,0,0,0,3,0,0,2},
{0,8,0,0,4,0,0,1,0},
{6,0,0,5,0,0,0,0,0},
{0,0,0,0,1,0,7,8,0},
{5,0,0,0,0,9,0,0,0},
{0,0,0,0,0,0,0,4,0}
};
int assign[81];
void print(){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
bool finish(int assign[])
{
for(int i = 0; i < 81; i++)
{
if(a[i / 9][i % 9] == 0)
{
return false;
}
}
return true;
}
bool judge(int x,int y){
for(int i=0;i<9;i++){
if(a[x][i]==a[x][y]&&i!=y)
return false;
}
for(int i=0;i<9;i++){
if(a[i][y]==a[x][y]&&i!=x)
return false;
}
for(int i=x/3*3;i<x/3*3+3;i++){
for(int j=y/3*3;j<y/3*3+3;j++){
if(a[i][j]==a[x][y]&&(i!=x||j!=y))
return false;
}
}
return true;
}
//int v = 0;
void BT(int level)
{
int v = 0;
if(finish(assign) == true)
{
print();
return;
}
while(assign[v] != 0)
{
v += 1;
}
//cout<<v<<endl;
if(assign[v] != 2)
{
assign[v] = 1;
for(int i = 1; i <= 9; i++)
{
a[v / 9][v % 9] = i;
bool constraintsOK = true;
if(judge(v / 9, v % 9) == false)
{
constraintsOK = false;
}
if(constraintsOK == true)
{
//print();
//system("pause");
BT(level + 1);
}
}
a[v / 9][v % 9] = 0;
assign[v] = 0;
//cout<< level<<endl;
return;
}
}
int main()
{
for(int i = 0; i < 81; i++)
{
if(a[i / 9][i % 9] != 0)
{
assign[i] = 2;
}
else
{
assign[i] = 0;
}
}
BT(0);
//cout<< finish(assign)<<endl;
}
相关文章推荐
- 回溯算法解数独问题(java版)
- 回溯算法解数独问题(java版)
- 数独的求解算法 回溯
- 数独游戏(sudoku)算法 回溯+剪枝
- 【算法分析】回溯法解数独(九宫格)算法
- Java回溯算法解数独问题
- 数独算法-递归与回溯
- 算法之6-回溯法解数独问题
- 算法思想06--回溯思想
- 【人工智能】算法--理解贝叶斯分类器
- 南邮算法分析与设计实验3 回溯法
- Java常用算法——搜索(dfs) & 回溯(全排列、八皇后、分苹果问题的详细解析)
- 算法入门6:回溯法
- 实验四 回溯算法和分支限界法 符号三角形问题
- 国际象棋“皇后”问题的回溯算法
- 算法实践——改良的求解数独的暴力搜索法
- 回溯算法详解
- 利用回溯算法求马周游问题
- [算法] 人工智能Java 坦克机器人系列
- 3109: [cqoi2013]新数独 (回溯)