1. 程式人生 > >[人工智慧]回溯演算法解數獨

[人工智慧]回溯演算法解數獨

今天在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;
}