📜  在给定条件下将8个数字填入网格

📅  最后修改于: 2021-05-24 19:15:43             🧑  作者: Mango

将数字1、2、3、4、5、6、7、8放入下图中的八个圆圈中,以使该序列中相邻的数字不相邻。例如,1不应与2相邻,而应与3、4、5、6、7、8相邻。

天真的算法
天真的算法将生成从1到8的数字的所有可能配置,以填充空单元格。尝试一种配置,直到找到正确的配置。

回溯算法
像所有其他Backtraking问题一样,我们可以通过将数字分配给空单元格来解决此问题。在分配号码之前,我们检查分配是否安全。我们基本上检查相邻的单元格(垂直,水平或对角线)是否不存在相同的数字。在检查安全性之后,我们分配编号,然后递归检查此分配是否导致解决方案。如果分配没有解决方案,那么我们尝试为当前空单元格输入下一个数字。如果没有任何数字(1到8)导致解,则返回false。

Find row, col of an unassigned cell
  If there is none, return true
  For digits from 1 to 8
    a) If there is no conflict for digit at row, col
        assign digit to row, col and recursively try fill in rest of grid
    b) If recursion successful, return true
    c) Else, remove digit and try another
  If all digits have been tried and nothing worked, return false
// A Backtracking program in
// C++ to solve given problem
#include 
#include 
  
#define N 3 // row of grid
#define M 4 // column of grid
#define UNASSIGNED -1
using namespace std;
  
/* Returns a boolean which indicates
whether any assigned entry within the
specified grid matches the given number. */
bool UsedInGrid(int grid[N][M], int num)
{
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++)
            if (grid[i][j] == num)
                return true;
    }
    return false;
}
  
/* Returns a boolean which indicates
whether it will be legal to assign
num to the given row, col location. */
bool isSafe(int grid[N][M], int row, int col, int num)
{
    /* Check if 'num' is not already placed in Whole Grid*/
    if (row == 0 && col == 1) {
  
        if (UsedInGrid(grid, num)
            || (abs(num - grid[row][col + 1]) <= 1)
            || (abs(num - grid[row + 1][col]) <= 1)
            || (abs(num - grid[row + 1][col - 1]) <= 1)
            || (abs(num - grid[row + 1][col + 1]) <= 1))
            return false;
    }
    else if (row == 0 && col == 2) {
        if (UsedInGrid(grid, num)
            || (abs(num - grid[row][col - 1]) <= 1)
            || (abs(num - grid[row + 1][col]) <= 1)
            || (abs(num - grid[row + 1][col + 1]) <= 1)
            || (abs(num - grid[row + 1][col - 1]) <= 1))
            return false;
    }
    else if (row == 1 && col == 0) {
        if (UsedInGrid(grid, num)
            || (abs(num - grid[row - 1][col + 1]) <= 1)
            || (abs(num - grid[row][col + 1]) <= 1)
            || (abs(num - grid[row + 1][col + 1]) <= 1))
            return false;
    }
    else if (row == 1 && col == 3) {
        if (UsedInGrid(grid, num)
            || (abs(num - grid[row - 1][col - 1]) <= 1)
            || (abs(num - grid[row][col - 1]) <= 1)
            || (abs(num - grid[row + 1][col - 1]) <= 1))
            return false;
    }
    else if (row == 2 && col == 1) {
        if (UsedInGrid(grid, num) 
        || (abs(num - grid[row - 1][col - 1]) <= 1) 
        || (abs(num - grid[row - 1][col]) <= 1) 
        || (abs(num - grid[row - 1][col + 1]) <= 1)
        || (abs(num - grid[row][col + 1]) <= 1))
            return false;
    }
    else if (row == 2 && col == 2) {
        if (UsedInGrid(grid, num) 
        || (abs(num - grid[row][col - 1]) <= 1)
        || (abs(num - grid[row - 1][col]) <= 1) 
        || (abs(num - grid[row - 1][col + 1]) <= 1) 
        || (abs(num - grid[row - 1][col - 1]) <= 1))
            return false;
    }
    else if (row == 1 && col == 1) {
        if (UsedInGrid(grid, num) 
        || (abs(num - grid[row][col - 1]) <= 1) 
        || (abs(num - grid[row - 1][col]) <= 1) 
        || (abs(num - grid[row - 1][col + 1]) <= 1) 
        || (abs(num - grid[row][col + 1]) <= 1)
        || (abs(num - grid[row + 1][col + 1]) <= 1) 
        || (abs(num - grid[row + 1][col]) <= 1))
            return false;
    }
    else if (row == 1 && col == 2) {
        if (UsedInGrid(grid, num) 
        || (abs(num - grid[row][col - 1]) <= 1) 
        || (abs(num - grid[row - 1][col]) <= 1) 
        || (abs(num - grid[row + 1][col - 1]) <= 1) 
        || (abs(num - grid[row][col + 1]) <= 1) 
        || (abs(num - grid[row - 1][col - 1]) <= 1) 
        || (abs(num - grid[row + 1][col]) <= 1))
            return false;
    }
    return true;
}
  
// This function finds an entry 
// in grid that is still unassigned
bool FindUnassignedLocation(int grid[N][M],
                        int& row, int& col)
{
    for (row = 0; row < N; row++)
        for (col = 0; col < M; col++) {
            if (grid[row][col] == UNASSIGNED)
                return true;
        }
    return false;
}
  
/* A utility function to print grid */
void printGrid(int grid[N][M])
{
    for (int i = 0; i < N; i++) {
        if (i == 0 || i == N - 1)
            cout << " ";
        for (int j = 0; j < M; j++) {
            if (grid[i][j] == 0)
                cout << " ";
            else
                cout << grid[i][j] << " ";
        }
        cout << endl;
    }
}
  
/* Takes a grid and attempts to assign values to
all unassigned locations in such a way to meet 
the requirements for this solution.*/
bool Solve(int grid[N][M])
{
    int row, col;
  
    // If there is no unassigned location, we are done
    if (!FindUnassignedLocation(grid, row, col))
        return true; // success!
  
    // consider digits 1 to 8
    for (int num = 1; num <= 8; num++) {
          
        // if looks promising
        if (isSafe(grid, row, col, num)) {
          
            // make tentative assignment
            grid[row][col] = num;
          
            // return, if success, yay!
            if (Solve(grid))
                return true;
          
            // failure, unmake & try again
            grid[row][col] = UNASSIGNED;
        }
    }
    return false; // this triggers backtracking
}
  
/* Driver Program to test above functions */
int main()
{
    // -1 means unassigned cells
    int grid[N][M] = { { 0, -1, -1, 0 },
                    { -1, -1, -1, -1 },
                    { 0, -1, -1, 0 } };
                      
    if (Solve(grid) == true)
        printGrid(grid);
    else
        cout << "Not possible";
      
    return 0;
}
输出:
3 5  
7 1 8 2 
  4 6