本文主要是介绍Day30 回溯算法part06 332. 重新安排行程 51. N 皇后 37. 解数独,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
回溯算法part06 332. 重新安排行程 51. N 皇后 37. 解数独
332. 重新安排行程
下面方法在leetcode用例中会有一处超时
class Solution {
private:vector<string> path={"JFK"};vector<string> res;void backtracking(vector<vector<string>>& tickets,string from,vector<bool>& used){ //used数组存放每张机票使用情况if(path.size()>tickets.size()){res=path; //找到第一个path后返回return;}for(int i=0;i<tickets.size();i++){if(tickets[i][0]==from&&!used[i]){used[i]=true;path.push_back(tickets[i][1]);backtracking(tickets,tickets[i][1],used);path.pop_back();used[i]=false;}if(res.size()){ //剪枝操作return; }}}public:static bool compare(const vector<string>& a,const vector<string>& b){return a[1]<b[1];}vector<string> findItinerary(vector<vector<string>>& tickets) {sort(tickets.begin(),tickets.end(),compare); //按照目的地排序,这样回溯遍历时就先找查找字典顺序最小的vector<bool> used(tickets.size(),false);backtracking(tickets,"JFK",used);return res;}
};
51. N 皇后
row进行回溯退出判定,chessboard数组方便每次回溯验证棋子是否合法
class Solution {
private:
vector<vector<string>> result;
// n 为输入的棋盘大小
// row 是当前递归到棋盘的第几行了
void backtracking(int n, int row, vector<string>& chessboard) {if (row == n) {result.push_back(chessboard);return;}for (int col = 0; col < n; col++) {if (isValid(row, col, chessboard, n)) { // 验证合法就可以放chessboard[row][col] = 'Q'; // 放置皇后backtracking(n, row + 1, chessboard);chessboard[row][col] = '.'; // 回溯,撤销皇后}}
}
bool isValid(int row, int col, vector<string>& chessboard, int n) {// 检查列for (int i = 0; i < row; i++) { // 这是一个剪枝if (chessboard[i][col] == 'Q') {return false;}}// 检查 45度角是否有皇后for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {if (chessboard[i][j] == 'Q') {return false;}}// 检查 135度角是否有皇后for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {if (chessboard[i][j] == 'Q') {return false;}}return true;
}
public:vector<vector<string>> solveNQueens(int n) {result.clear();vector<string> chessboard(n, string(n,'.')); //绘制棋盘backtracking(n, 0, chessboard);return result;}
};
37. 解数独
二刷细细研究
class Solution {
private:
bool backtracking(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++) { // (i, j) 这个位置放k是否合适if (isValid(i, j, k, board)) {board[i][j] = k; // 放置kif (backtracking(board)) return true; // 如果找到合适一组立刻返回board[i][j] = '.'; // 回溯,撤销k}}return false; // 9个数都试完了,都不行,那么就返回false}}}return true; // 遍历完没有返回false,说明找到了合适棋盘位置了
}
bool isValid(int row, int col, char val, vector<vector<char>>& board) {for (int i = 0; i < 9; i++) { // 判断行里是否重复if (board[row][i] == val) {return false;}}for (int j = 0; j < 9; j++) { // 判断列里是否重复if (board[j][col] == val) {return false;}}int startRow = (row / 3) * 3;int startCol = (col / 3) * 3;for (int i = startRow; i < startRow + 3; i++) { // 判断9方格里是否重复for (int j = startCol; j < startCol + 3; j++) {if (board[i][j] == val ) {return false;}}}return true;
}
public:void solveSudoku(vector<vector<char>>& board) {backtracking(board);}
};
这篇关于Day30 回溯算法part06 332. 重新安排行程 51. N 皇后 37. 解数独的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!