刷题(7)-回溯法

目录

 

简介:

回溯的通用模板:

有无解:

有多少个解:

最好的解:

一个例子(1到n的n位数全排列):


简介:

回溯法主要用在递归的树型问题中,该算法实际上是一个类似枚举的搜索尝试过程,在搜索过程中寻找问题的解,当发现当前问题状态无解时,就“回溯”返回,尝试别的路径。

判断是否可以用回溯法很简单,拿到一个问题,你感觉如果不穷举一下就没法知道答案,那就可以开始回溯了。

一般回溯的问题有三种:

  1. Find a path to success 有没有解
  2. Find all paths to success 求所有解

            a) 求所有解的个数

            b) 求所有解的具体信息

     3.  Find the best path to success 求最优解

理解回溯:给一堆选择, 必须从里面选一个. 选完之后我又有了新的一组选择. 

回溯可以抽象为一棵树,我们的目标可以是找这个树有没有good leaf,也可以是问有多少个good leaf,也可以是找这些good leaf都在哪,也可以问哪个good leaf最好,分别对应上面所说回溯的问题分类。

good leaf都在leaf上。good leaf是我们的goal state,leaf node是final state,是解空间的边界。

回溯的通用模板:

void dfs()//参数用来表示状态  
{  
    if(到达终点状态)  
    {  
        ...//根据题意添加  
        return;  
    }  

    for(当前状态的每一个可能性){
        if(该可能性合法(比如没被标记过等等)){       // 剪枝
            
            修改操作;//根据题意来添加  
            标记;  
            dfs(设置下一位);  
            (还原标记);  
            //是否还原标记根据题意  
            //如果加上(还原标记)就是 回溯法  

        }   
        
    }
}  

关于回溯的三种问题,模板略有不同,
第一种,返回值是true/false。
第二种,求个数,设全局counter,返回值是void;求所有解信息,设result,返回值void。
第三种,设个全局变量best,返回值是void。

有无解:

bool dfs(){      //参数用来表示状态  
    if n is a leaf node {
        if the leaf is a goal node, return true
        else return false
    } else {
        for each child c of n {
            if solve(c) succeeds, return true
        }
        return false
    }
}

 

有多少个解:

void solve(Node n) {
    if n is a leaf node {
        if the leaf is a goal node, count++, return;
        else return
    } else {
        for each child c of n {
            solve(c)
        }
    }
}

最好的解:

void solve(Node n) {
    if n is a leaf node {
        if the leaf is a goal node, update best result, return;
        else return
    } else {
        for each child c of n {
            solve(c)
        }
    }
}

一个例子(1到n的n位数全排列):

//回溯法 全排列
//从1-n的 n位数全排列
void dfs(int*res, int*visit, int step, int n){
	if(step == n){
		for(int i=0;i<n;i++){
			cout<<res[i];
		}
		cout<<endl;
		return;
	}
	
	for(int i=1;i<=n;i++){
		if(visit[i] ==0){
			res[step] = i;
			visit[i] = 1;
			dfs(res,visit,step+1,n);
			visit[i] = 0;
		}
	}
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值