【递归】方格填数(回溯法求解)

【递归】方格填数(回溯法求解)

问题描述

见 方格填数

解决方案

  • 在创建数组时,先初始化为-2(因为要填入0~9的数,如果默认设置为0则不好分辨这个位置是否已经填上数字了)
  • 接着占位arr[0][0]arr[2][3]-1,表示这两个位置不可达。
  • 接着使用回溯法(带循环的递归) 穷举所有可能情况,每次在插入值时既需要判断当前位置是否已填入,还要检查邻居位置是否有相邻数字。
  • 如果整个方格已经填满,并满足约束条件,则方案个数+1,并回溯到上一个状态,继续进行搜索。

参考代码

#include
#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

你可能感兴趣的:(数据结构与算法,递归算法,回溯)