算法基础——回溯法

目录

一、算法思想

二、算法要素

三、回溯法求解0-1背包问题代码 


一、算法思想

回溯法是一种选优搜索法,按照选优条件深度优先搜索,以达到目标。当搜索到某一步,发现原先选择并不是最优或达不到目标,就退回一步重新选择。其核心思想为“能进则进,进不了则换,换不了则退”

二、算法要素

1.解空间

确定问题的解的形式,以及对解的分量的显约束。解空间就是所有可能解组成的空间。

2.解空间结构

解空间树,有子集树,排列树等。

3.搜索解空间

隐约束指对能否得到问题的可行解或最优解做出的约束,也称为剪枝函数,包括约束函数和限界函数

回溯法解题的关键是设计有效的显约束和隐约束。

三、回溯法求解0-1背包问题代码 


//回溯法求解0-1背包问题
#include 
#include 
#include 

#define M 105
using namespace std;
int i, j, n, W;                 //n表示n个物品,w表示购物车的容量
double w[M], v[M];              //w[i]表示第i个物品的重量,v[i]表示第i个物品的价值
bool x[M];                      //x[i]表示第i个物品是否放入购物车
double cw;                      //当前重量
double cp;                      //当前价值
double bestp;                   //当前最优价值
bool bestx[M];                  //当前最优解


//计算上界,查看剩余物品的总价值和当前已选中物品的价值之和
double Bound(int i)
{
	//剩余物品为第i~n种物品
	int rp = 0;
	while (i <= n)
	{
		rp += v[i];
		i++;
	}
	return rp + cp;
}

//回溯搜索,按照约束条件和限界条件搜索求解
void Backtrack(int t)           //t表示当前扩展节点在第t层
{
	if (t > n)                     //已经到达叶子节点
	{
		for (j = 1; j <= n; j++)
		{
			bestx[j] = x[j];
		}
		bestp = cp;               //保存当前最优解
		return;
	}
	if (cw + w[t] <= W)             //如果满足约束条件则搜索左子树,左子树代表物品被选取
	{
		x[t] = 1;
		cw += w[t];
		cp += v[t];
		Backtrack(t + 1);           //深度优先搜索第t+1层              
		cw -= w[t];                 //回归时即向上回溯,要把增加的值减去
		cp -= v[t];
	}
	if (Bound(t + 1) > bestp)       //如果满足限界条件则搜索右子树
	{
		x[t] = 0;
		Backtrack(t + 1);
	}
}

//背包问题初始化
void Knapsack()
{
	//初始化
	cw = 0;              
	cp = 0;
	bestp = 0;
	double sumw = 0.0;      //用来统计所有物品的总重量
	double sumv = 0.0;      //用来统计所有物品的总价值
	for (i = 1; i <= n; i++)
	{
		sumv += v[i];
		sumw += w[i];
	}
	if (sumw <= W)
	{
		bestp = sumv;
		cout << "放入购物车的物品最大价值为: " << bestp << endl;
		cout << "所有的物品均放入购物车。";
		return;
	}
	Backtrack(1);
	cout << "放入购物车的物品最大价值为: " << bestp << endl;
	cout << "放入购物车的物品序号: ";
	for (i = 1; i <= n; i++)
	{
		if (bestx[i] == 1)
			cout << i << " ";
	}
	cout << endl;
}

int main()
{
	cout << "请输入物品的个数n: ";
	cin >> n;
	cout << "请输入购物车的容量W: ";
	cin >> W;
	cout << "请依次输入每个物品的重量w和价值v,用空格分开:";
	for (i = 1; i <= n; i++)
		cin >> w[i] >> v[i];
	Knapsack();

	return 0;
}

你可能感兴趣的:(C++编程)