回溯算法

回溯算法复习整理

回溯算法的框架(递推)

result=[]
def backtrace(路径,选择列表)
	if满足结束条件
		result.add(路径)
		return
	for选择in选择列表
		做选择
		将该选择从选择列表中移除
		路径.add(选择)
    	backtrack(路径, 选择列表)
    	撤销选择
    	路径.remove(选择)
    	将该选择再加入选择列表

前序遍历再代码进入某个节点之前的时间点进行访问;后序遍历在离开某个节点后的时间点进行访问。

回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。

4皇后问题

#include <iostream>
#include <stdio.h>
#include <stdlib.h>	
	
	
using namespace std;

const int N = 100;
int a[N][N];//棋盘
int M[N];//M[j]=1表示第j列有皇后
int L[N];//L[j]=1,表示该左斜线上有皇后
int R[N];//R[j]=1,表示该右斜线上有皇后
int n,num,count;


void print(){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
}

//第i行的解决策略
int solution(int i){
	for(int j=0;j<n;j++){//j<n而不是j<i
		//做选择,某列某斜线上是否存在皇后
		if(!M[j] && !L[i+j] && !R[i-j+1]){
			a[i][j]=i+1;
			M[j]=1;
			L[i+j]=1;
			R[i-j+1]=1;//更新状态
			
			//结束条件,当行到了棋盘的最下面,直接输出结果
			if(i=n-1){
				cout << endl;
				print();
				count++;
			}
			//进行下一行决策
			else sovle(i+1);
			a[i][j]=0;//去除皇后,回溯
			M[j]=L[i+j]=R[i-j+n]=0;
		}
	}
	return count;
}



int main() {
	cin >> n;
	num = solution(n);
	cout << n << endl;
	return 0;
}

n皇后问题(摘自labuladong的算法)

vector<vector<string>> res;

/* 输入棋盘边长 n,返回所有合法的放置 */
vector<vector<string>> solveNQueens(int n) {
    // '.' 表示空,'Q' 表示皇后,初始化空棋盘。
    vector<string> board(n, string(n, '.'));
    backtrack(board, 0);
    return res;
}

// 路径:board 中小于 row 的那些行都已经成功放置了皇后
// 选择列表:第 row 行的所有列都是放置皇后的选择
// 结束条件:row 超过 board 的最后一行
void backtrack(vector<string>& board, int row) {
    // 触发结束条件
    if (row == board.size()) {
        res.push_back(board);
        return;
    }

    int n = board[row].size();
    for (int col = 0; col < n; col++) {
        // 排除不合法选择
        if (!isValid(board, row, col)) 
            continue;
        // 做选择
        board[row][col] = 'Q';
        // 进入下一行决策
        backtrack(board, row + 1);
        // 撤销选择
        board[row][col] = '.';
    }
}

/* 是否可以在 board[row][col] 放置皇后? */
bool isValid(vector<string>& board, int row, int col) {
    int n = board.size();
    // 检查列是否有皇后互相冲突
    for (int i = 0; i < n; i++) {
        if (board[i][col] == 'Q')
            return false;
    }
    // 检查右上方是否有皇后互相冲突
    for (int i = row - 1, j = col + 1; 
            i >= 0 && j < n; i--, j++) {
        if (board[i][j] == 'Q')
            return false;
    }
    // 检查左上方是否有皇后互相冲突
    for (int i = row - 1, j = col - 1;
            i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] == 'Q')
            return false;
    }
    return true;
}

算法的时间复杂度是O(n^(n+1)),非常地大

https://zhuanlan.zhihu.com/p/93530380
https://blog.csdn.net/weiyuefei/article/details/79316653

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值