回溯法解决9宫格问题

                                 算法之回溯法—-解决9宫格问题

          最近一直在看算法,原因是马上的算法竞赛就要到来了,今天回顾了一下常用算法中的回溯法。

       回溯法也是深度优先遍历的一种方法,不过在回溯法进行的同时,将不可能的结果直接pass掉,这样就大大提高了程序的效率,回溯法求解八皇后问题在网上是非常多的,我这里就不举例了,今天我们用回溯法来求解难倒很多数学家的9宫格问题。问题是这样的:

        玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。

数独的答案都是唯一的,所以,多个解也称为无解。直接附上代码啦,便于大家一起分析。

#include<stdio.h>
int  result=0;                         //多少种结果
void showsudu(int data[9][9])
{
	result++;
	for(int row=0;row<9;row++)
	{
		for(int col=0;col<9;col++)
		{
			printf("%d ",data[row][col]);
		}
		printf("\n");
	}
	printf("\n");
}
bool check(int data[9][9],int row,int col,int k) //判断是否可以将第row行、第col列的数设为k
{
	int m,n;
	
	for(n=0;n<9;n++)              //判断行,是否有k
	{
		if(data[row][n] == k)
			return false;
	}
	
	for(m=0;m<9;m++)         
	{
		if(data[m][col] == k)     //判断列,是否有k
			return false;
	}
	
	int p=(row/3)*3,q=(col/3)*3;  //下面判断所在小九宫格,是否有k
	for(m=p;m<p+3;m++)
	{
		for(n=q;n<q+3;n++)
		{
			if(data[m][n] == k)
				return false;
		}
	}
	
	return true;                  //可行,返回true
}

void sudo(int data[9][9],int number)   //data为81个格,编号0-80,number为第几个格
{
	int temp[9][9];
	int row,col;
	for(row=0;row<9;row++)
	{
		for(col=0;col<9;col++)
			temp[row][col]=data[row][col];
	}
	row=number/9; col=number%9;        //求出第number个格对应的行数和列数
	if(data[row][col] != 0)            //已经有原始数据
	{
		if (number == 80)              //是最后一个格子,输出独数
			showsudu(temp);
		else                           //不是最后一个格子,求下一个格子
			sudo(temp,number+1);
	}
	else                               //else下面是没有数的情况
	{
		for(int k=1;k<=9;k++)          //分别用1-9的数填格
		{
			if(check(temp,row,col,k))  //判断k是否可以填入第row行、第col列的格子
			{
				temp[row][col]=k;      //n填入第row行、第col列的格子
				if(number == 80)
					showsudu(temp);
				else
					sudo(temp,number+1);

				temp[row][col]=0;       //恢复为0,循环用下一个k去尝试
			}
		}
	}
}


int main()
{
	/*int data[9][9]={
		{0,0,5,3,0,0,0,0,0},
		{8,0,0,0,0,0,0,2,0},
		{0,7,0,0,1,0,5,0,0},
		{4,0,0,0,0,5,3,0,0},
		{0,1,0,0,7,0,0,0,6},
		{0,0,3,2,0,0,0,8,0},
		{0,6,0,5,0,0,0,0,9},
		{0,0,4,0,0,0,0,3,0},
		{0,0,0,0,0,9,7,0,0}};  //81个格
	//*/
	int data[9][9]={
		{0,0,5,3,0,0,0,0,0},
		{8,0,0,0,0,0,0,2,0},
		{0,7,0,0,1,0,5,0,0},
		{4,0,0,0,0,5,3,0,0},
		{0,1,0,0,7,0,0,0,6},
		{0,0,3,2,0,0,0,8,0},
		{0,6,0,5,0,0,0,0,9},
		{0,0,4,0,0,0,0,3,0},
		{7,0,0,0,0,9,6,4,5}};  //81个格
		
		/*printf("请输入数独中的原始数据,没有数据的用0代替。\n");
		for(int row=0;row<9;row++)
		{
			printf("请输入第%d行的9个数:",row+1);
			for(int col=0;col<9;col++)
				scanf("%d",&data[row][col]);
		}
		printf("数独的解为:\n\n");
		//*/
		
		sudo(data,0);            //开始填第1个格

		if(result==0)
			printf("此数独无解!\n");
		else
			printf("数独%d个解!\n",result);

		return 0;
}


    原文作者:回溯法
    原文地址: https://blog.csdn.net/u013473520/article/details/44963341
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞