回溯-数独求解
问题
数独(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("\n"); } } /* 测试 */ 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; }