算法基礎——回溯法

目錄

一、算法思想

二、算法要素

三、回溯法求解0-1揹包問題代碼 


一、算法思想

回溯法是一種選優搜索法,按照選優條件深度優先搜索,以達到目標。當搜索到某一步,發現原先選擇並不是最優或達不到目標,就退回一步重新選擇。其核心思想爲“能進則進,進不了則換,換不了則退”

二、算法要素

1.解空間

確定問題的解的形式,以及對解的分量的顯約束。解空間就是所有可能解組成的空間。

2.解空間結構

解空間樹,有子集樹,排列樹等。

3.搜索解空間

隱約束指對能否得到問題的可行解或最優解做出的約束,也稱爲剪枝函數,包括約束函數和限界函數

回溯法解題的關鍵是設計有效的顯約束和隱約束。

三、回溯法求解0-1揹包問題代碼 


//回溯法求解0-1揹包問題
#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];              //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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章