1. 八皇后问题
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
思路:使用一个数组gEightQueen存储第i行的皇后摆在第gEightQueen[i]列的位置上
步骤一:对于第0行,一共有八个位置可以选择,逐一选择
步骤二:对于以后的每一行,一共有八个位置可以选择,确定位置后需要判断该位置放置元素是否与前面的行冲突,如果冲突,继续在剩余的位置中选择测试。如果不冲突,则继续向下递归,递归结束后应当将改行的元素置0。
步骤三:当递归到第7行,选择位置不冲突则找到了一种情况,将总的情况统计数加1。
#include<iostream> using namespace std; static int gEightQueen[8] = { 0 }, gCount = 0; void print()//输出每一种情况下棋盘中皇后的摆放情况 { for (int i = 0; i < 8; i++) { int inner; for (inner = 0; inner < gEightQueen[i]; inner++) cout << "0"; cout <<"#"; for (inner = gEightQueen[i] + 1; inner < 8; inner++) cout << "0"; cout << endl; } cout << "========================== "; } int check_pos_valid(int loop, int value)//检查是否存在有多个皇后在同一行/列/对角线的情况 { int index; int data; for (index = 0; index < loop; index++) { data = gEightQueen[index]; if (value == data) return 0; if ((index + data) == (loop + value)) return 0; if ((index - data) == (loop - value)) return 0; } return 1; } void eight_queen(int index) { int loop; for (loop = 0; loop < 8; loop++) { if (check_pos_valid(index, loop)) { gEightQueen[index] = loop; if (7 == index) { gCount++, print(); gEightQueen[index] = 0; return; } eight_queen(index + 1); gEightQueen[index] = 0; } } } int main(int argc, char*argv[]) { eight_queen(0); cout << "total=" << gCount << endl; return 0; }
2. 数独问题
解法:只需要求出一个解,solve()返回布尔类型对于判断是否完成解十分有用
步骤一:依此遍历数独中所有的元素,如果不存在'.',说明已经获得了解,如果存在'.',说明需要继续向下求解。
步骤二:存在'.',依此遍历字符1-9,判断是否满足行,列条件,如果满足,将该值赋给'.'所在位置的元素,继续向下求解,如果有解,返回true,解已经求得,如果没有解,将'.'所修改的值继续改到'.',否则在判断有效性的函数上会出现问题。
#include "pch.h" #include <iostream> #include <vector> using namespace std; bool isValid(vector<vector<char>>& board, int row, int col, char value) { // 测试行,列,3 * 3 矩阵有效 for (int i = 0; i < board.size(); i++) { if (board[row][i] == value) { return false; } if (board[i][col] == value) { return false; } if (board[i / 3 + 3 * (row / 3)][i % 3 + 3 * (col / 3)] == value) { return false; } } return true; } bool solve(vector<vector<char>>& board) { for (int i = 0; i < board.size(); i++) { for (int j = 0; j < board[0].size(); j++) { if (board[i][j] == '.') { for (char k = '1'; k <= '9'; k++) { if (isValid(board, i, j, k)) { board[i][j] = k; if (solve(board)) { return true; } board[i][j] = '.'; // 更换一个k值继续计算 } } return false; } } } return true; } void solveSudoku(vector<vector<char>>& board) { if (board.empty() || board.size() == 0) { return; } solve(board); } int main() { vector<vector<char>> board = { {'5', '3', '.', '.', '7', '.', '.', '.', '.'}, {'6', '.', '.', '1', '9', '5', '.', '.', '.'}, {'.', '9', '8', '.', '.', '.', '.', '6', '.'}, {'8', '.', '.', '.', '6', '.', '.', '.', '3'}, {'4', '.', '.', '8', '.', '3', '.', '.', '1'}, {'7', '.', '.', '.', '2', '.', '.', '.', '6'}, {'.', '6', '.', '.', '.', '.', '2', '8', '.'}, {'.', '.', '.', '4', '1', '9', '.', '.', '5'}, {'.', '.', '.', '.', '8', '.', '.', '7', '9'} }; solveSudoku(board); for (int i = 0; i < board.size(); i++) { for (int j = 0; j < board[0].size(); j++) { cout << board[i][j] << ' '; } cout << endl; } }