zoukankan      html  css  js  c++  java
  • 回溯-数独求解

    问题

    数独(Sūdoku)是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复

    给定一个 9×9 二维数组 ‘grid[9][9]’ 表示初始的局面,判断试放可求解,并输出最终的局面.

    回溯法求解

    对每一个空格子在放置一个数字前,我们先检查这个该数字对当前局面存在冲突,即检查当前行和当前列,和当前位置所走的 3×3的子格子.并递归的判断,当前放置的数字,是否可以求得一个解.

    如果,不可以求解,则尝试下一个.如果1-9都尝试完了,则返回false.

    下面是C++实现:

    #include <stdio.h>
    #define UNASSIGNED 0
     
    // NxN 的大小
    #define N 9
     
    // 是否还有未放置的位置
    bool FindUnassignedLocation(int grid[N][N], int &row, int &col);
     
    // 在位置 grid[row][col]处,是否可以放置num
    bool isSafe(int grid[N][N], int row, int col, int num);
     
    /* 回溯法求解 */
    bool SolveSudoku(int grid[N][N])
    {
        int row, col;
     
        // 都已经放置完,则返回true
        if (!FindUnassignedLocation(grid, row, col))
           return true; // success!
     
        for (int num = 1; num <= 9; num++)
        {
            if (isSafe(grid, row, col, num))
            {
                // 放置棋子
                grid[row][col] = num;
     
                // return, if success, yay!
                if (SolveSudoku(grid))
                    return true;
     
                // 失败, 设置为 未放置的 & 再一次尝试
                grid[row][col] = UNASSIGNED;
            }
        }
        return false; 
    }
     
    bool FindUnassignedLocation(int grid[N][N], int &row, int &col)
    {
        for (row = 0; row < N; row++)
            for (col = 0; col < N; col++)
                if (grid[row][col] == UNASSIGNED)
                    return true;
        return false;
    }
    
    bool UsedInRow(int grid[N][N], int row, int num)
    {
        for (int col = 0; col < N; col++)
            if (grid[row][col] == num)
                return true;
        return false;
    }
     
    bool UsedInCol(int grid[N][N], int col, int num)
    {
        for (int row = 0; row < N; row++)
            if (grid[row][col] == num)
                return true;
        return false;
    }
     
    bool UsedInBox(int grid[N][N], int boxStartRow, int boxStartCol, int num)
    {
        for (int row = 0; row < 3; row++)
            for (int col = 0; col < 3; col++)
                if (grid[row+boxStartRow][col+boxStartCol] == num)
                    return true;
        return false;
    }
     
    bool isSafe(int grid[N][N], int row, int col, int num)
    {
        return !UsedInRow(grid, row, num) &&
               !UsedInCol(grid, col, num) &&
               !UsedInBox(grid, row - row%3 , col - col%3, num);
    }
     
    void printGrid(int grid[N][N])
    {
        for (int row = 0; row < N; row++)
        {
           for (int col = 0; col < N; col++)
                 printf("%2d", grid[row][col]);
            printf("
    ");
        }
    }
     
    /* 测试 */
    int main()
    {
        int grid[N][N] = {{3, 0, 6, 5, 0, 8, 4, 0, 0},
                          {5, 2, 0, 0, 0, 0, 0, 0, 0},
                          {0, 8, 7, 0, 0, 0, 0, 3, 1},
                          {0, 0, 3, 0, 1, 0, 0, 8, 0},
                          {9, 0, 0, 8, 6, 3, 0, 0, 5},
                          {0, 5, 0, 0, 9, 0, 6, 0, 0},
                          {1, 3, 0, 0, 0, 0, 2, 5, 0},
                          {0, 0, 0, 0, 0, 0, 0, 7, 4},
                          {0, 0, 5, 2, 0, 6, 3, 0, 0}};
        if (SolveSudoku(grid) == true)
              printGrid(grid);
        else
             printf("No solution exists");
     
        return 0;
    }
  • 相关阅读:
    配置samba
    extern c
    剑指offer 孩子们的游戏
    剑指offer 扑克牌顺子
    剑指offer 翻转单词顺序列
    剑指offer 左旋转字符串
    mysql查看或显示当前存在多少数据库
    vim替换
    平衡二叉树
    将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分
  • 原文地址:https://www.cnblogs.com/secret114/p/4550427.html
Copyright © 2011-2022 走看看