【递归】方格填数(回溯法求解)
问题描述
见 方格填数
解决方案
- 在创建数组时,先初始化为
-2
(因为要填入0~9
的数,如果默认设置为0
则不好分辨这个位置是否已经填上数字了) - 接着占位
arr[0][0]
和arr[2][3]
为-1
,表示这两个位置不可达。 - 接着使用回溯法(带循环的递归) 穷举所有可能情况,每次在插入值时既需要判断当前位置是否已填入,还要检查邻居位置是否有相邻数字。
- 如果整个方格已经填满,并满足约束条件,则方案个数
+1
,并回溯到上一个状态,继续进行搜索。
参考代码
#include<stdio.h>
#define row 3
#define col 4
#define NUM_MAX 9
const int position[8][2] {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
//相邻数字判断
int constraint_judge(int i, int j, int arr[row][col]){
int k;
int cur = arr[i][j];
int flag = 1; //满足约束
for(k = 0; k < 8; k++){
int temp_i = i + position[k][0];
int temp_j = j + position[k][1];
if((temp_i >= 0 && temp_i < row) && (temp_j >= 0 && temp_j < col)){ //边界判断
if(arr[temp_i][temp_j] != -1 && (arr[temp_i][temp_j] == (cur + 1) || arr[temp_i][temp_j] == (cur - 1))){
flag = 0;
break;
}
}
}
return flag;
}
//回溯法求解填数方案
int func(int arr[row][col], int num){
int count = 0;
int i,j;
if(num == NUM_MAX + 1){
return 1;
}
for(i = 0; i < row; ++i){
for(j = 0; j < col; ++j){
if(arr[i][j] == -2){
arr[i][j] = num;
if(constraint_judge(i,j,arr) == 0){ //不满足约束,则回溯
arr[i][j] = -2; //回溯
continue;
}
count += func(arr,num + 1);
arr[i][j] = -2; //回溯
}
}
}
return count;
}
int main(int argc, char const *argv[])
{
int arr[row][col] = {{-2,-2,-2,-2},{-2,-2,-2,-2},{-2,-2,-2,-2}};
arr[0][0] = -1; //占位
arr[row - 1][col - 1] = -1; //占位
int count = func(arr, 0); //插入数字0
printf("填数方案:%d\n",count);
}
---
填数方案:1580