回溯法(深度优先法)速解

匿名 (未验证) 提交于 2019-12-02 23:06:17

算法解题部件:

  1. 根据问题定义解空间,这可以类似于概率论中的样本空间S,空间中包含所有的可能结果,多以n叉树实现;
  2. 约束条件,对解空间中的解做出约束,以缩减搜索解空间成本,避免不必要的搜索;
  3. 界限条件,根据约束条件,我们可以找到问题的所有可行解,当需要求得最优解是,我们需要设置界限条件,即当满足该条件时,我们可能找到最优解。

当我们需要找到所有可行解的时候,则只需要设定约束函数即可,若要求最优解,就需要两条件同时上阵了!

下面我们以对简单的0-1背包问题为例,学习回溯法:

问题分析&算法设计

很明显,在n个宝物中选择几个宝物带走,即从集合S中选择一个子集,要求子集的总重量不超过W,而且价值最大

针对于S中的每一个宝物,只会存在“拿”(1)与“不拿”(0)的问题,由此,我们可以得出解空间为{x1,x2,x3.....xn},其中xi=0/1;不难看出,解空间中一共有2^n种可能解,我们可以将解空间定义为深度为n的二叉树)(取左为1,取右为0)。

约束条件:

  • 搜索过程中,沿着拓展节点的左分支拓展,表示装入宝物。由此可知,我们在拓展时应该判断约束条件是否成立,成立则左,不成立则右。
  • 在每个节点判断界限条件,若不成立,则该节点为死结点,无须向下搜索。

代码示例:

 #include <iostream> #include <string> #include <algorithm> #define M 105 using namespace std;  int i, j, n, w;  //n表示n个物品,w表示船容量 double W[M], V[M]; bool x[M];      double cw, cp, bestp;  //cw,cp为当前船重量与价值,bestp为当前为止最优的价值记录 bool bestx[M];  //当前最优问题解  //计算已确定的物品和剩余的物品总价值 double Bound(int i) { 	int rp = 0; 	while (i <= n) 	{ 		rp += V[i]; 		i++; 	} 	return cp+rp; }  //用于 void Backtrack(int t) { 	if (t > n)//到达树末的叶子 	{ 		for (j = 1; j <= n; j++) 		{ 			bestx[j] = x[j]; 			//保存当前最优解,为什么不用判断就直接保存呢?因为有Bound的关系,能走到叶子,必然比之前的最优解更优 		} 		bestp = cp; 		return; 	} 	if (cw + W[t] <= w) 	{ 		x[t] = 1; 		cw += W[t]; 		cp += V[t]; 		Backtrack(t + 1); 		cw -= W[t]; 		cp -= V[t]; 	} 	if (Bound(t+1) > bestp)   //判断是否搜索右子树 	{ 		x[t] = 0; 		Backtrack(t + 1); 	} }  void Knapsack(double w, int n) { 	//初始化 	cw = 0; cp = 0; 	bestp = 0; 	double sumw = 0.0; 	double sumv = 0.0;  //用于记录所有物品的总重量和总价值 	for (i = 1; i <= n; i++) 	{ 		sumw += W[i]; 		sumv += V[i]; 	} 	if (sumw <= w) 	{ 		bestp = sumv; 		cout << "所有物品均放入背包,最大价值为: " << bestp << endl; 		return; 	}  	//开始搜索 	Backtrack(1); 	cout << "放入船的最大价值为: " << bestp << endl; 	cout << "放入的物品的序号为: "; 	for (i = 0; i <= n; i++) 	{ 		if (bestx[i] == 1) 		{ 			cout << i << " "; 		} 	} 	cout << endl; }  int main() { 	cout << "请输入物品的个数n: "; 	cin >> n; 	cout << "请输入船的容量w: "; 	cin >> w; 	cout << "请依次输入每个物品的重量和价值,以空格分开: "; 	for (i = 1; i <= n; i++) 	{ 		cin >> W[i] >> V[i]; 	} 	return 0; }

文章来源: https://blog.csdn.net/wangtao990503/article/details/88590817
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!