算法之回溯法----解决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; }